diff --git a/new/apps/web/src/php/404.html b/new/apps/web/src/php/404.html new file mode 100755 index 0000000..aaa99d7 --- /dev/null +++ b/new/apps/web/src/php/404.html @@ -0,0 +1,71 @@ + + + + + + Page Not Found + + + + + + + + + +
+ +
+ +

Page Not Found

+

Sorry, but the view you were trying to access has expired or is invalid.

+ + + diff --git a/new/apps/web/src/php/README.md b/new/apps/web/src/php/README.md new file mode 100755 index 0000000..c179737 --- /dev/null +++ b/new/apps/web/src/php/README.md @@ -0,0 +1,13 @@ +# specified +An Open Source viewer engine for Specify JSON exports. See [Specify](https://github.com/Spec-ify/specify) for more information. + +Written mostly in PHP, visually based (in large) on Spark + + +## Style guide +You should prefer to conform to the style of the surrounding code over personal preference. + +### Language Conventions +Language specific styling should conform to the [Wordpress Developer Style Guide](https://developer.wordpress.org/coding-standards/wordpress-coding-standards/javascript/), with the following changes: + +- Shorthand PHP tags are allowed \ No newline at end of file diff --git a/new/apps/web/src/php/archive.php b/new/apps/web/src/php/archive.php new file mode 100644 index 0000000..1569436 --- /dev/null +++ b/new/apps/web/src/php/archive.php @@ -0,0 +1,57 @@ + + + + Specified + + + + + + + + +
+

Specify Archive Login

+
+
+
+ +
+
+
+ +
+ +
+
+ + + + + +'; + } +} +?> diff --git a/new/apps/web/src/php/assets/brave.png b/new/apps/web/src/php/assets/brave.png new file mode 100755 index 0000000..6019343 Binary files /dev/null and b/new/apps/web/src/php/assets/brave.png differ diff --git a/new/apps/web/src/php/assets/chrome.png b/new/apps/web/src/php/assets/chrome.png new file mode 100755 index 0000000..699df4e Binary files /dev/null and b/new/apps/web/src/php/assets/chrome.png differ diff --git a/new/apps/web/src/php/assets/dl.png b/new/apps/web/src/php/assets/dl.png new file mode 100755 index 0000000..1a9e311 Binary files /dev/null and b/new/apps/web/src/php/assets/dl.png differ diff --git a/new/apps/web/src/php/assets/edge.png b/new/apps/web/src/php/assets/edge.png new file mode 100755 index 0000000..baf8c62 Binary files /dev/null and b/new/apps/web/src/php/assets/edge.png differ diff --git a/new/apps/web/src/php/assets/firefox.png b/new/apps/web/src/php/assets/firefox.png new file mode 100755 index 0000000..0c6ae7e Binary files /dev/null and b/new/apps/web/src/php/assets/firefox.png differ diff --git a/new/apps/web/src/php/assets/gx.png b/new/apps/web/src/php/assets/gx.png new file mode 100755 index 0000000..4f89c4e Binary files /dev/null and b/new/apps/web/src/php/assets/gx.png differ diff --git a/new/apps/web/src/php/assets/logo.png b/new/apps/web/src/php/assets/logo.png new file mode 100755 index 0000000..97cae00 Binary files /dev/null and b/new/apps/web/src/php/assets/logo.png differ diff --git a/new/apps/web/src/php/assets/specify-glass-black-256x256.png b/new/apps/web/src/php/assets/specify-glass-black-256x256.png new file mode 100644 index 0000000..d3d1d2d Binary files /dev/null and b/new/apps/web/src/php/assets/specify-glass-black-256x256.png differ diff --git a/new/apps/web/src/php/assets/specify-glass-dynamic.svg b/new/apps/web/src/php/assets/specify-glass-dynamic.svg new file mode 100644 index 0000000..10c7733 --- /dev/null +++ b/new/apps/web/src/php/assets/specify-glass-dynamic.svg @@ -0,0 +1,11 @@ + + specify-glass-black + + + diff --git a/new/apps/web/src/php/assets/specify-glass-white-256x256.png b/new/apps/web/src/php/assets/specify-glass-white-256x256.png new file mode 100644 index 0000000..3f65598 Binary files /dev/null and b/new/apps/web/src/php/assets/specify-glass-white-256x256.png differ diff --git a/new/apps/web/src/php/assets/vivaldi.png b/new/apps/web/src/php/assets/vivaldi.png new file mode 100755 index 0000000..b3c3405 Binary files /dev/null and b/new/apps/web/src/php/assets/vivaldi.png differ diff --git a/new/apps/web/src/php/common.php b/new/apps/web/src/php/common.php new file mode 100644 index 0000000..7827902 --- /dev/null +++ b/new/apps/web/src/php/common.php @@ -0,0 +1,128 @@ + 3) $timeString .= ' style="color:#BF616A;"'; + $timeString .= '>' . $days . ' day'; + if ($days != 1) { + $timeString .= 's'; + } + $timeString .= ', '; + } + + + // Add the number of hours to the string + if ($hours) { + $timeString .= $hours . ' hour'; + if ($hours != 1) { + $timeString .= 's'; + } + $timeString .= ', '; + } + + // Add the number of minutes to the string + if ($minutes) { + $timeString .= $minutes . ' minute'; + if ($minutes != 1) { + $timeString .= 's'; + } + $timeString .= ', '; + } + // Add the number of seconds to the string A3BE8C + if ($seconds) { + if ($days || $hours || $minutes) $timeString .= 'and '; + $timeString .= $seconds . ' second'; + if ($seconds != 1) { + $timeString .= 's'; + } + } + + return $timeString; +} + +// https://maxchadwick.xyz/blog/stripping-a-query-parameter-from-a-url-in-php +function http_strip_query_param($url, $param) +{ + $pieces = parse_url($url); + $query = []; + if ($pieces['query']) { + parse_str($pieces['query'], $query); + unset($query[$param]); + $pieces['query'] = http_build_query($query); + } + + return $pieces['path'] . ($pieces['query'] ? '?' : '') . $pieces['query']; +} diff --git a/new/apps/web/src/php/composer.json b/new/apps/web/src/php/composer.json new file mode 100644 index 0000000..cd5e56e --- /dev/null +++ b/new/apps/web/src/php/composer.json @@ -0,0 +1,12 @@ +{ + "name": "spec-ify/specified", + "description": "A web viewer for Specify", + "type": "project", + "require-dev": { + "phpstan/phpstan": "^1.12", + "phpstan/phpstan-strict-rules": "^1.6" + }, + "require": { + "basuke/sveltekit-php-backend": "^1.0" + } +} diff --git a/new/apps/web/src/php/composer.lock b/new/apps/web/src/php/composer.lock new file mode 100644 index 0000000..fee2dd9 --- /dev/null +++ b/new/apps/web/src/php/composer.lock @@ -0,0 +1,177 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "dd9d46f7c51dcaf756972c44f4db5448", + "packages": [ + { + "name": "basuke/sveltekit-php-backend", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/basuke/sveltekit-php-backend.git", + "reference": "a27c0c0208a8dc33a1f99d8dcfc72fd1302f0cb7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/basuke/sveltekit-php-backend/zipball/a27c0c0208a8dc33a1f99d8dcfc72fd1302f0cb7", + "reference": "a27c0c0208a8dc33a1f99d8dcfc72fd1302f0cb7", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Basuke\\SvelteKit\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Basuke Suzuki", + "email": "basuke@mac.com" + } + ], + "description": "Supplemental package to support SvelteKit PHP Backend Vite Plugin", + "homepage": "https://github.com/basuke/sveltekit-php-backend", + "keywords": [ + "SvelteKit", + "backend", + "svelte", + "vite" + ], + "support": { + "issues": "https://github.com/basuke/sveltekit-php-backend/issues", + "source": "https://github.com/basuke/sveltekit-php-backend/tree/1.0.0" + }, + "time": "2023-05-21T17:15:35+00:00" + } + ], + "packages-dev": [ + { + "name": "phpstan/phpstan", + "version": "1.12.7", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "dc2b9976bd8b0f84ec9b0e50cc35378551de7af0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/dc2b9976bd8b0f84ec9b0e50cc35378551de7af0", + "reference": "dc2b9976bd8b0f84ec9b0e50cc35378551de7af0", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "time": "2024-10-18T11:12:07+00:00" + }, + { + "name": "phpstan/phpstan-strict-rules", + "version": "1.6.1", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan-strict-rules.git", + "reference": "daeec748b53de80a97498462513066834ec28f8b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/daeec748b53de80a97498462513066834ec28f8b", + "reference": "daeec748b53de80a97498462513066834ec28f8b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.12.4" + }, + "require-dev": { + "nikic/php-parser": "^4.13.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-deprecation-rules": "^1.1", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^9.5" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Extra strict and opinionated rules for PHPStan", + "support": { + "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.6.1" + }, + "time": "2024-09-20T14:04:44+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": {}, + "prefer-stable": false, + "prefer-lowest": false, + "platform": {}, + "platform-dev": {}, + "plugin-api-version": "2.6.0" +} diff --git a/new/apps/web/src/php/delete-files.sh b/new/apps/web/src/php/delete-files.sh new file mode 100755 index 0000000..bbc950c --- /dev/null +++ b/new/apps/web/src/php/delete-files.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +# https://stackoverflow.com/a/1482133 +SCRIPT_DIR=$(dirname -- "$( readlink -f -- "$0"; )") + +cd $SCRIPT_DIR + +# held files list must contain absolute paths +HELD_FILES_LIST="$SCRIPT_DIR/held_files" + +# get files older than 24 hours +OLD_FILES=$( find $SCRIPT_DIR/files -mindepth 1 -mtime +0 -type f ) + +for fileName in $OLD_FILES +do + if grep -Fxq "$fileName" "$HELD_FILES_LIST"; then + echo "$fileName held" + else + rm $fileName + fi +done diff --git a/new/apps/web/src/php/doom-scroll.php b/new/apps/web/src/php/doom-scroll.php new file mode 100644 index 0000000..fa50a33 --- /dev/null +++ b/new/apps/web/src/php/doom-scroll.php @@ -0,0 +1,1784 @@ + time()) { + $validversions = $validversions . $eolitem['latest'] . ' '; + } + } + + //The lines below are for the loop that calculates total RAM/CPU used. + //CPU doesn't work right now because we are not able to efficiently get the CPU usage of each running process. + $working_set = 0; + $cpu_percent = 0; + + foreach ($json_data['System']['RunningProcesses'] as $process) { + $working_set += $process['WorkingSet']; // RAM + $cpu_percent += $process['WorkingSet']; // CPU + } + + $ram_used = number_format($working_set / 1073741824, 2, '.', ''); + + $total_ram = 0; + + if ($json_data['Hardware']['Ram']){ + //Don't ask me why this is an old fashioned for loop, I got carried away. + //Getting the total amount of RAM in the system. + $ram_sticks = safe_count($json_data['Hardware']['Ram']); + + foreach ($json_data['Hardware']['Ram'] as $stick) { + $capacity = $stick['Capacity']; + if ($capacity != 0) { + $ram_size = floor($stick['Capacity'] / 1000); + $total_ram += $ram_size; + } + } + //Calculating how much of it is used + $ram_used_percent = round((float)$ram_used / (float)$total_ram * 100); + } + + //Basic string to time php function to take the generation date and turn it into a usable format. + $ds = strtotime($json_data['Meta']['GenerationDate']); + $test_time = timeConvert($json_data['BasicInfo']['Uptime']); + + //Uservar paths split function + $paths = $json_data['System']['UserVariables']['Path']; + + // Split the paths into an array using the semicolon as the delimiter + $path_array = explode(';', $paths); + + // Notable Software and SMBIOS + include('lists.php'); + // Set up the reference list + $referenceListInstalled = $json_data['System']['InstalledApps']; + $referenceListRunning = $json_data['System']['RunningProcesses']; + + $pupsFoundInstalled = array(); + foreach ($referenceListInstalled as $installed) { + foreach ($notableSoftwareList as $pups) { + preg_match('/\b(' . strtolower($pups) . ')\b/', strtolower($installed['Name']), $matches, PREG_OFFSET_CAPTURE); + if ($matches) { + array_push($pupsFoundInstalled, $installed['Name']); + } + } + } + $pupsFoundInstalled = array_unique($pupsFoundInstalled); + + $pupsFoundRunning = array(); + foreach ($referenceListRunning as $running) { + foreach ($notableSoftwareList as $pups) { + preg_match('/\b(' . strtolower($pups) . ')\b/', strtolower($running['ProcessName']), $matches, PREG_OFFSET_CAPTURE); + if ($matches) { + array_push($pupsFoundRunning, $running['ProcessName']); + } + } + } + $pupsFoundRunning = array_unique($pupsFoundRunning); + + $dumpLink = ""; + if (isset($json_data['System']['DumpZip'])) { + $strippedLink = str_replace("\n", '', $json_data['System']['DumpZip']); + if (filter_var($strippedLink, FILTER_VALIDATE_URL)) { + $dumpLink = $strippedLink; + } + } + + /** + * Return table layout for a data array + * @param string[][] $arr + * @param string[] $cols cols can be modified in the transform function. if a column is not present in the array, it will be blank + * @param Closure $transform an optional function that takes the row `function (&$row) {` as an argument and can modify it + * @param string $noDataMessage what to output for an empty array + */ + function array_table_iter(?array $arr, array $cols, $transform = null, string $noDataMessage = 'No Data'): string + { + $res = ""; + $colLength = count($cols); + if (!$arr) { + // we need these so DataTables doesn't get mad + $fillerTds = str_repeat("", $colLength - 1); + return "$noDataMessage$fillerTds"; + } + foreach ($arr as $row) { + if ($transform) { + $transform($row); + } + $res .= ''; + foreach ($cols as $col) { + $res .= '' . ($row[$col] ?? '') . ''; + } + $res .= ''; + } + return $res; + } + + /** + * Return table layout for a data object (key => value) + * @param string[][] $arr + */ + function object_table_iter(?array $arr): string + { + $res = ""; + if (!$arr) return ''; + foreach ($arr as $key => $val) { + $res .= "$key$val"; + } + return $res; + } +?> + + + + + + Profile <?= $profile_name ?> | Specified + + + + + + + "/> + + "/> + + + + + + + + + + + + + + + +
+ +

Profile Information

+ + + + + + + + + + + + + + + + + + + + +
Profile
Created UTC
Runtimems
Specify Version
+ +

General Notes

+ $latestBuildInt) { + $os_insider = true; + $eoltext = 'Insider'; + $eolcolor = "red"; + } else { + $eoltext = "EOL"; + $eolcolor = "red"; + } + + // Up-to-Date-ness + $oscheck = ''; + if (strpos($latestver, $json_data['BasicInfo']['Version']) !== false) { + $oscheck = 'Up-to-date'; + $oscolor = "green"; + } else { + $oscheck = 'Not Up-to-Date'; + $oscolor = "red"; + } + + if (($eolcolor == "red" && $oscolor == "green") + || ($eolcolor == "green" && $oscolor == "red")) $osenglish = 'but'; + else $osenglish = 'and'; +?> + + +

Notable Software

+ + + +

OS Information

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Edition
Build #
Version
Install Date
Uptime
Domain
Hostname
Username
UAC
Boot Mode
Secure Boot
Boot State
+ +

Hardware

+ +

CPU

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name
Manufacturer
Socket Designation
Current Clock Speed
# of Enabled Cores
Thread Count
+

Database Results

+

+ + +
+ +

RAM

+ + + + + + + + + + + + + + + + "; + } else { + echo " + + + + + + + + "; + } + } + ?> + +
DIMMManufacturerModelSpeedCapacity
$ram_locationNot Detected
$ram_location$ram_manufacturer$ram_part{$ram_speed}MHz{$ram_size}MB
+ +

Pagefile

+ + + + + + + + + + + + + + + + + + + +
File Path
Allocated Base Size MB
Current Usage MB
Peak Usage MB
+ +

Motherboard

+ + + + + + + + + + + + + + + + + + + + + + + format('Y-m-d'); + } else { + $formattedbiosdate = "unknown"; + } + ?> + + + + + + + + + + + +
Motherboard Product
Motherboard Manufacturer
BIOS Manufacturer
Version
Release Date
Base
Serial Number
+ +

TPM

+ + + + + + + + + + + + + + + + +
Status
Manufacturer Version
Version
+ +

GPUs

+ + + + + + + + + + + + + + + + '; + } + ?> + +
NameVRAMResolutionRefresh Rate
' . $gpu['Description'] . '' . $gpu['AdapterRAM'] / pow(2, 20) . ' MB' . '' . $gpu['CurrentHorizontalResolution'] . ' x ' . $gpu['CurrentVerticalResolution'] . '' . $gpu['CurrentRefreshRate'] . 'Hz' . '
+ +

Displays

+ + + + + + + + + + + + + + + + + + + '; + } + ?> + +
NameVRAMModeMonitorConnection
' . $monitor['Name'] . '' . $monitor['DedicatedMemory'] . '' . $monitor['CurrentMode'] . '' . $monitor['MonitorModel'] . '' . $monitor['ConnectionType'] . '
+ +

Temperatures

+ + + + + + + + + +
HardwareSensorTemperature (°C)
+ +

SMBIOS Information

+ + + $value) { + if ($key == 'BiosCharacteristics') { + $bcStringList = []; + foreach ($value as $characteristic) { + if (isset($biosCharacteristics[$characteristic])) { + $bcStringList[] = $biosCharacteristics[$characteristic]; + } + } + echo ' + + + + + '; + continue; + } + if ($key == 'BIOSVersion' || $key == 'ListOfLanguages') { + echo ' + + + + + '; + continue; + } + + echo " + + + + + "; + } + ?> + +
' . $key . '' . implode('
', $bcStringList) . '
' . $key . '' . safe_implode('
', $value) . '
$key$value
+ + +

Devices

+

Table will not be sortable until database lookups finish

+ + + + + + + + + + + + + + + +
StatusNameDescriptionDIDVendor (Database)Device (Database)PCIe Subsystem (Database)
+ +

Drivers

+ + + + + + + + + + + + + +
NameFriendly NameManufacturerDIDVersion
+ +

Storage

+ $drive) { + $drive_size_raw = $drive['DiskCapacity']; + $drive_free_raw = getDriveFree($drive); + $drive_taken_raw = $drive_size_raw - $drive_free_raw; + $drive_size = floor(bytesToGigabytes($drive_size_raw)); + $drive_taken = floor(bytesToGigabytes($drive_taken_raw)); + // the drive size can sometimes be z ero if the drive is failing + if ($drive_taken != 0 && $drive_size != 0) { + $drive_percentage = round((float)$drive_taken / (float)$drive_size * 100); + } else $drive_percentage = 0; + + $letters = array_filter( + array_column($drive['Partitions'], 'PartitionLetter') + ); + $lettersString = implode(", ", $letters); + $lettersStringDisplay = empty($lettersString) ? '' : "($lettersString)"; + + echo ' +

' . $drive['DeviceName'] . '

+ + + + + + + + + + + + ' . '' . ' + ' . '' . ' + ' . '' . ' + ' . '' . ' + ' . '' . ' + +
NameSN#CapacityFree
' . $drive['DeviceName'] . '' . $drive['SerialNumber'] . '' . $drive['DiskNumber'] . '' . floor(bytesToGigabytes($drive['DiskCapacity'])) . 'GB' . floor(bytesToGigabytes(getDriveFree($drive))) . 'GB
+

Partitions

+
+ '; + + foreach ($drive['Partitions'] as $part) { + $part_size = $part['PartitionCapacity']; + $part_taken = $part_size - $part['PartitionFree']; + $part_size_mb = bytesToMegabytes($part_size); + $part_taken_mb = ceil(bytesToMegabytes($part_taken)); + $part_display = ""; + if (!empty($part['PartitionLabel'])) { + $part_display .= $part['PartitionLabel']; + if (isset($part['PartitionLetter'])) { + $part_display .= " ({$part['PartitionLetter']})"; + } + } else if (isset($part['PartitionLetter'])) { // and not partition label + $part_display = $part['PartitionLetter']; + } + if (!empty($part_display)) + $part_display .= '
'; + $fs_display = $part['Filesystem'] ?? 'Unknown'; + + // The "drive size + 1" is a terrible fix for division by 0 errors + echo ' +
+ + ' . $part_display /* this will already have
if not empty */ . ' + ' . $fs_display . '
+ ' . "$part_taken_mb / $part_size_mb MB Used" . ' +
+
+
+ '; + } + + // The "drive size + 1" is a terrible fix for division by 0 errors + echo ' +
+ + + + + + + + + + + + + + + '; + foreach ($drive['Partitions'] as $part) { + echo ' + + + + + + + + + + + '; + } + echo ' + +
LabelLetterCapacityFreeFS TypeCfgMgr Error CodeLast Error CodeDirty Bit
' . $part['PartitionLabel'] . '' . $part['PartitionLetter'] . '' . floor(bytesToMegabytes($part['PartitionCapacity'])) . ' MB' . floor(bytesToMegabytes($part['PartitionFree'])) . ' MB' . $part['Filesystem'] . '' . $part['CfgMgrErrorCode'] . '' . $part['LastErrorCode'] . '' . $part['DirtyBitSet'] . '
+

SMART

+ '; + if (isset($drive['SmartData'])) { + echo ' +
+ + + + + + + + + + ' . array_table_iter($drive['SmartData'], ['Id', 'Name', 'RawValue']) . ' + +
IndexNameValue
+ '; + } else { + echo + ' +
Sorry, no SMART data was found for this device.
+ '; + } + echo '
'; + } +?> + +

Audio Devices

+ + + + + + + + + + + + +
Device IDManufacturerNameStatus
+ +

Power Profiles

+ + + + + + + + + + + $arr['IsActive'] = $arr['IsActive'] ? 'Yes' : 'No') ?> + +
NameDescriptionInstance PathActive?
+ +

Batteries

+ + + + + + + + + + + + '; + } + ?> + +
NameManufacturerChemistryDesign CapacityCurrent Full Charge Capacity
No batteries detected
+ +

Variables

+ +

User Variables

+ + + $val) { + echo ' + + + + + '; + } + ?> + +
' . $key . '' . implode('
', explode(';', $val)) . '
+ +

System Variables

+ + + $val) { + echo ' + + + + + '; + } + ?> + +
' . $key . '' . implode('
', explode(';', $val)) . '
+ +

Startup Tasks

+ + + + + + + + + + + +
App NameApp PathTimestamp
+ +

Installed Updates

+ + + + + + + + + + +
UpdateInstalled On
+ +

Browser Extensions

+ +

Profile + ""

+ + + + + + + + + + + +
NameVersionDescription
+ + + +

Running Processes

+ + + + + + + +
PIDNamePathRAM (MB)
+ +

Installed Apps

+ + + + + + + + + +
NameVersionInstall Date
+ + +

Windows Store

+ + + + + + + + + + +
NameProgram IDVersionVendor
+ + +

Services

+ + + + + + + + + + + +
StateNameCaptionPathStart Mode
+ +

Tasks

+ + + + + + + + + + + ', $row['TriggerTypes']); + }) + ?> + +
StateActiveNamePathAuthorTriggers
+ +

Network

+

Adapters

+' . $nic["Description"] . ' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + '; + + if (isset($nic["LinkSpeed"])) { + echo ' + + + + + '; + } + + if (isset($nic["PhysicalAdapter"]) && $nic["PhysicalAdapter"]) { + echo ' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + '; + } + + echo '
Name' . $nic['Description'] . '
Interface Index' . $nic['InterfaceIndex'] . '
MAC' . $nic["MACAddress"] . '
Gateway(s)' . safe_implode('
', $nic["DefaultIPGateway"]) . '
DHCP State' . $nic["DHCPEnabled"] . '
DHCP Lease Expiry' . $nic["DHCPLeaseExpires"] . '
DHCP Lease Obtained' . $nic["DHCPLeaseObtained"] . '
DHCP Server' . $nic["DHCPServer"] . '
DNS Domain' . $nic["DNSDomain"] . '
DNS Hostname' . $nic["DNSHostName"] . '
DNS Suffixes' . safe_implode('
', $nic['DNSDomainSuffixSearchOrder']) . '
IP Enabled?' . $nic["IPEnabled"] . '
IP(s)' . safe_implode('
', $nic['IPAddress']) . '
Subnet' . safe_implode('
', $nic['IPSubnet']) . '
Physical Adapter?' . (($nic['PhysicalAdapter'] ? 'Yes' : 'No') ?? 'unknown') . '
Link Speed' . round($nic["LinkSpeed"] / 1_000_000) . 'Mbps
Static DNS Servers?' . ($nic['DNSIsStatic'] ? 'Yes' : 'No') . '
DNS Servers' . safe_implode('
', array_merge($nic['DNSServerSearchOrder'] ?? [], $ipv6_dns)) . '
Full Duplex?' . ($nic["FullDuplex"] ? 'Yes' : 'No') . '
Media Connection State' . $nic["MediaConnectState"] . '
Media Duplex State' . $nic["MediaDuplexState"] . '
MTU Size' . $nic["MtuSize"] . '
Name' . $nic["Name"] . '
Operational Status' . ($nic["OperationalStatusDownMediaDisconnected"] ? 'Down - Media Disconnected' : '') . '
Permanent Address' . $nic["PermanentAddress"] . '
Promiscuous Mode' . $nic["PromiscuousMode"] . '
State' . $nic["State"] . '
'; + } + +?> + +

Connections

+ + + + + + + + + + + +
Local IPLocal PortRemote IPRemote PortProcess Name
+ +

Routes Table

+ + + + + + + + + + + + +
RouteDestinationInterfaceMaskMetricNext Hop
+ +

Others

+

Recieve Side Scaling

+ + + + + + + +
RecieveSideScaling
+

Auto Tuning Level Local

+ + + + +
+ +

Hosts File

+'; + $lines = explode("\n", $json_data['Network']['HostsFile']); + foreach ($lines as $line) { + echo "$line"; + } + echo ''; +?> + +Events + "; + } + + if ($unexpectedShutdownsPresent) { +?> +

Unexpected Shutdowns

+ + + + + + + + + + + + + +
TimestampBugcheck CodeP1P2P3P4Power Button Recorded
+MachineCheck Exceptions"; + foreach ($json_data['Events']['MachineCheckExceptions'] as $exception_item) { + echo " + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Timestamp{$exception_item['Timestamp']}
MCE Status Register Valid{$exception_item['MciStatusRegisterValid']}
Error Overflow{$exception_item['ErrorOverflow']}
Uncorrected Error{$exception_item['UncorrectedError']}
Error Reporting Enabled{$exception_item['ErrorReportingEnabled']}
Processor Context Corrupted{$exception_item['ProcessorContextCorrupted']}
Poisoned Data{$exception_item['PoisonedData']}
Extended Error Code{$exception_item['ExtendedErrorCode']}
MCA Error Code{$exception_item['McaErrorCode']}
Error Message{$exception_item['ErrorMessage']}
TransactionType{$exception_item['TransactionType']}
Memory Hierarchy Level{$exception_item['MemoryHierarchyLevel']}
Request Type{$exception_item['RequestType']}
Participation{$exception_item['Participation']}
Timeout{$exception_item['Timeout']}
Memory Or IO{$exception_item['MemoryOrIo']}
Memory Transaction Type{$exception_item['MemoryTransactionType']}
Channel Number{$exception_item['ChannelNumber']}
+ "; + } + } + + if ($pcieWheaPresent) { + ?> +

PCIe WHEA Errors

+ + + + + + + + + + +
TimestampVendor IDDevice IDMatched Device
+WHEA Errors"; + foreach ($json_data['Events']['WheaErrorRecords'] as $record) { + echo " +

[{$record['ErrorHeader']['Severity']}] {$record['ErrorHeader']['NotifyType']} - {$record['ErrorHeader']['Timestamp']}

+
+Error Header + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Timestamp{$record['ErrorHeader']['Timestamp']}
Signature{$record['ErrorHeader']['Signature']}
Revision{$record['ErrorHeader']['Revision']}
Signature End{$record['ErrorHeader']['SignatureEnd']}
Section Count{$record['ErrorHeader']['SectionCount']}
Severity{$record['ErrorHeader']['Severity']}
Valid Bits{$record['ErrorHeader']['ValidBits']}
Length{$record['ErrorHeader']['Length']}
Timestamp{$record['ErrorHeader']['Timestamp']}
Platform ID{$record['ErrorHeader']['PlatformId']}
Partition ID{$record['ErrorHeader']['PartitionId']}
Creator ID{$record['ErrorHeader']['CreatorId']}
Notify Type{$record['ErrorHeader']['NotifyType']}
Record ID{$record['ErrorHeader']['RecordId']}
Flags{$record['ErrorHeader']['Flags']}
Persistence Info{$record['ErrorHeader']['PersistenceInfo']}
+
+
+Error Packets +
+ "; + + for ($i = 0; $i < count($record['ErrorDescriptors']); $i++) { + $descriptor = $record['ErrorDescriptors'][$i]; + $packet = $record['ErrorPackets'][$i]; + echo " + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Section Offset{$descriptor["SectionOffset"]}
Section Length{$descriptor["SectionLength"]}
Revision{$descriptor["Revision"]}
Valid Bits{$descriptor["ValidBits"]}
Flags{$descriptor["Flags"]}
Section Type{$descriptor["SectionType"]}
FRU ID{$descriptor["FRUId"]}
Section Severity{$descriptor["SectionSeverity"]}
FRU Text{$descriptor["FRUText"]}
+
$packet
+ "; + } + + echo " +
+
+ "; + } + } +?> + +
+

Debug Log

+ '; + $lines = explode("\r\n", $json_data['DebugLogText']); + foreach ($lines as $line) { + echo "$line"; + } + echo ''; + ?> +
+
+ + diff --git a/new/apps/web/src/php/favicon.ico b/new/apps/web/src/php/favicon.ico new file mode 100644 index 0000000..5d90978 Binary files /dev/null and b/new/apps/web/src/php/favicon.ico differ diff --git a/new/apps/web/src/php/gesp-mode.php b/new/apps/web/src/php/gesp-mode.php new file mode 100644 index 0000000..eb95bf4 --- /dev/null +++ b/new/apps/web/src/php/gesp-mode.php @@ -0,0 +1,1168 @@ + + + + + + + + + + + + + + + + + + + +
+
+⬆ +
+ +Local: +setTimezone(new DateTimeZone('UTC')); +$utc = $date->format('Y-m-d\TH:i:s.u\Z'); +?> + +UTC: + +Specify Version: + +

System Information

+Edition: + +Version: () +Install date: + +Uptime: + +Hostname: + +Domain: + +Boot mode: + +Boot state: + +

Notes

+

+Static Core Count found set.
'; +} + +$hostFileHash = $json_data['Network']['HostsFileHash']; +$hostFileCheck = "2D6BDFB341BE3A6234B24742377F93AA7C7CFB0D9FD64EFA9282C87852E57085" !== $hostFileHash; + +if ($hostFileCheck) { + echo 'Hosts file has been modified from stock, it has been appended to bottom of this page
'; +} + +if($json_data['System']['RecentMinidumps']!=0){ + echo 'There have been '.$json_data['System']['RecentMinidumps'].' Minidumps found
'; +} +foreach ($json_data['System']['ChoiceRegistryValues'] as $regkey) { + if ($regkey['Value'] && !in_array($regkey['Value'], $defaultRegKeys[$regkey['Name']])){ + echo 'Registry Value ' . $regkey['Name'] . ' found set, value of ' . $regkey['Value'] . '
'; + } +} +?>

+'.$pup.' Found installed
'; + } + foreach($pupsfoundRunning as $pup){ + echo ''.$pup.' Found Running
'; + } + ?> + +

Sections

+
+

Hardware Basics

+

Security Information

+

BIOS

+

System Variables

+

User Variables

+

Installed updates

+

Startup Tasks

+

Powerprofiles

+

Running Processes

+

Services

+

Installed Applications

+

Browser Extensions

+

Network Configuration

+

Network Connections

+

drivers and device versions

+

USB Devices

+

Devices with issues

+

Audio Devices

+

Disk Layouts(WIP)

+

SMART

+
+ +

Hardware Basics

+ + + + + + + + + + + "; + } + ?> +
DeviceSensorTemperature
{$temperature['Hardware']}{$temperature['SensorName']}{$adjustedtemp} C
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "; + + endforeach; + ?> + +
PartManufacturerProductTemperatureDriver
CPUWIP
Motherboard
Video CardWIP{$gpu['Description']}WIPWIP
+ + + + + + + + + + + + + + + + + + + + "; + } + ?> +
GPU NameMonitorModelOut TypeCurrent Mode
{$monitors['Name']}{$monitors['MonitorModel']}{$monitors['ConnectionType']}{$monitors['CurrentMode']}
+ + + + + + + + + + + + + + Name + Manaufacturer + Chemistry + Design Capacity + Full Charge Capacity + Remaining Life Percentage + "; + + foreach ($json_data['Hardware']['Batteries'] as $batteries){ + echo " + + {$batteries['Name']} + {$batteries['Manufacturer']} + {$batteries['Chemistry']} + {$batteries['Design_Capacity']} + {$batteries['Full_Charge_Capacity']} + {$batteries['Remaining_Life_Percentage']} + + "; + } + + echo ""; + } + ?> + + + + + + + + + + + + + + + + + + + "; + ?> + +
TotalRAM
{$capacity}GB
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "; + } + else{ + echo " + + + + + + + + + "; + } + } + ?> + +
ManufacturerConfiguredclockspeedDevicelocatorCapacitySerialnumberPartNumber
{$ram['Manufacturer']}{$ram['ConfiguredSpeed']}{$ram['DeviceLocation']}{$ram['Capacity']}{$ram['SerialNumber']}{$ram['PartNumber']}
------
+ + +

Security Information

+ + + + + + + + "; + $avcount += 1; + } + + if (!empty($json_data['Security']['FwList'])){ + foreach ($json_data['Security']['FwList'] as $fw){ + $fwstring = $fw[$fwcount]; + echo " + + + + + "; + $fwcount += 1; + } + } + + else { + echo " + + + "; + } + + ?> + + + + + + + + + + + + + + '.$json_data['Security']['SecureBootEnabled'].''; + } + else{ + echo ''; + } + ?> + +
Antivirus{$avcount}:{$av}
Firewall{$fwcount}:{$fw}
Firewall:Assume Defender
UAC Enabled:
UAC Level:
SecureBoot:False
+

TPM

+ + + + + + + + + + + + + + + + + + + + + + +
ActivatedEnabledOwnedVersionSpec Version
+

BIOS

+ + + + + + + + + + + + + + + + + + + + + "; + } + ?> + +
ManufacturerSMBIOSBIOSVersionNameVersion
{$bios['Manufacturer']}{$bios['SMBIOSBIOSVersion']}{$bios['Name']}{$bios['Version']}
+ +

System Variables

+ + + + + + + + + $value) { + echo " + + + "; + } + ?> + +
NameValue
{$name}{$value}
+ +

User Variables

+ + + + + + + + + $value) { + echo " + + + "; + } + ?> + +
NameValue
{$name}{$value}
+ +

Installed updates

+ + + + + + + + + + + + + + + + + + + + "; + } + ?> + +
DescriptionHotFix IDInstalled On
{$ih['Description']}{$ih['HotFixID']}{$ih['InstalledOn']}
+ + +

Startup Tasks

+ + + + +

Powerprofiles

+ + + + + + + + + + + + + + + + "; + } // heh pp - k9 + ?> + +
ProfileIsActive
{$pp['ElementName']}{$pp['IsActive']}
+ +

Running Processes WIP

+Total RAM usage: WIP + + + + + + + + + + + + + + + + + + + + + + + + + + + "; + } + ?> + +
NamePIDMem (M)Path
{$rp['ProcessName']}{$rp['Id']}{$set}MB{$rp['ExePath']}
+ +

Services

+ + + + + + + + + + + + + + + + "; + + if ($serv['State'] == "Stopped"){ + echo ""; + } + + else { + echo ""; + } + + echo " + + "; + } + ?> + +
StatusStartTypeDisplayName
StoppedRunning{$serv['StartMode']}{$serv['Name']}
+ +

Installed Apps

+ + + + + + + + + + + + + + + + + "; + } + ?> + +
InstallDateDisplayName
{$ia['InstallDate']}{$ia['Name']}
+ +

Browser Extensions

+ + + + + + + + + + + + + + + + + + + + + "; + + foreach($browser1['Extensions'] as $ext){ + if($ext){ + echo " + + + + + "; + } } + } + } + ?> + +
Author WIPnamedescriptionversion
{$browser['Name']} {$browser1['name']}
{$ext['name']}{$ext['description']}{$ext['version']}
+ +

Network Configuration

+ + + + + + + + + + + + + + $printnet){ + if(is_array($printnet)){ + $printnet=implode(", ",$printnet); + } + if (is_bool($printnet)) { + $printnet = $printnet ? "True" : "False"; + } + echo " + + + "; + }} + ?> +
FieldValue
{$key}{$printnet}
+ + +

Network Connections WIP

+ + + + + + + + + + + + + + + + + + + + + + + + + + "; + } + ?> + +
Local AddressLocal PortRemote AddressRemote PortStateProcessProcess Path
{$netconnection['LocalIPAddress']}{$netconnection['LocalPort']}{$netconnection['RemoteIPAddress']}{$netconnection['RemotePort']}State{$netconpidname}{$netconpidpath}
+

Drivers and device versions

+ + + + + + + + + + + + + + + + + "; + } + ?> + +
Driver NameDriver Version
{$drv['DeviceName']}{$drv['DriverVersion']}
+ + +

USB Devices

+ + + + + + + + + + + + + + + + + + + + "; + }} + ?> + +
Device NameDevice DescriptionDevice IDDevice Status
{$usb['Name']}{$usb['Description']}{$usb['DeviceID']}{$usb['Status']}
+ +

Devices with Issues

+ + + + + + + + + + + + + + + + + + "; + }} + ?> + +
Device StatusDevice IDDevice Name
{$issueDevice['Status']}{$issueDevice['DeviceID']}{$issueDevice['Name']}
+

Audio devices

+ + + + + + + + + + + + + + + + + "; + } + ?> + +
ManufacturerProductName
{$aud['Manufacturer']}{$aud['Name']}
+ + +

Disk layouts

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "; + + $storage1count += 1; + } + } + ?> + +
OperationalStatus WIPDiskNumberPartitionNumberSize (GB)IsActive WIPIsBoot WIPIsReadOnly WIP
{$storage['DiskNumber']}$storage1count$partitioncap
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "; + + $storage1count += 1; + } + } + ?> + +
Drive Type WIPFile SystemFile System LabelAllocation Unit Size WIPDrive Letter WIPSize Remaining (GB)Size Total (GB)
{$storage1['Filesystem']}{$storage1['PartitionLabel']}$partitionrem$partitioncap
+ + +

SMART WIP

+ + + + + + + "; + + foreach($smart['SmartData'] as $smart1) { + echo " + + + "; + } + } + ?> + +
Model:{$smart['DeviceName']}
{$smart1['Name']}{$smart1['RawValue']}
+ + Host File Hash (ripemd160): " + . $hostFileHash + . "

" + . $json_data['Network']['HostsFile']; +} + +?> + +

Runtime

+ + + + + + + + + + + + + + + + + + + "; + + ?> + +
SecondsMilliseconds
$seconds$millisecond
+
+ + + diff --git a/new/apps/web/src/php/index.html b/new/apps/web/src/php/index.html new file mode 100755 index 0000000..3c429ba --- /dev/null +++ b/new/apps/web/src/php/index.html @@ -0,0 +1,74 @@ + + + + + Specified + + + + + + + + + + + + +
+
+
+ + +
+
+
+
+

Viewer

+

This website is an online viewer for Specify data.

+

In order to use it:

+
    +
  1. Generate a json via Specify +
  2. +
+
+ +
+ +
+ + +

About

+

Specify is a snapshot viewer

+ +

More information about Specify can be found on GitHub, or you can come chat with us on Discord.

+ +
+
+ Massive Shoutout to Spark +
+ + + + diff --git a/new/apps/web/src/php/json-check.php b/new/apps/web/src/php/json-check.php new file mode 100644 index 0000000..7ca838c --- /dev/null +++ b/new/apps/web/src/php/json-check.php @@ -0,0 +1,41 @@ + NULL, + 'Meta' => array ( + 'ElapsedTime' => NULL, + 'GenerationDate' => NULL + ), + 'BasicInfo' => array ( + 'Edition' => NULL, + 'Version' => NULL, + 'FriendlyVersion' => NULL + ), + 'System' => array ( + 'UserVariables' => NULL, + 'SystemVariables' => NULL, + 'RunningProcesses' => NULL, + 'Services' => NULL, + 'InstalledApps' => NULL, + 'InstalledHotfixes' => NULL + ), + 'Hardware' => array ( + 'Ram' => NULL, + 'Cpu' => NULL, + 'Gpu' => NULL + ), + 'Security' => array ( + 'AvList' => NULL, + 'FwList' => NULL, + 'Tpm' => NULL + ), + + 'Network' => array ( + 'Adapters' => NULL, + 'HostsFile' => NULL, + 'HostsFileHash' => NULL + ), + 'DebugLogText' => NULL + ); +?> diff --git a/new/apps/web/src/php/lists.php b/new/apps/web/src/php/lists.php new file mode 100644 index 0000000..9ae5191 --- /dev/null +++ b/new/apps/web/src/php/lists.php @@ -0,0 +1,119 @@ + "BIOS Characteristics are not supported.", + 4 => "ISA is supported.", + 5 => "MCA is supported.", + 6 => "EISA is supported.", + 7 => "PCI is supported.", + 8 => "PC card (PCMCIA) is supported.", + 9 => "Plug and Play is supported.", + 10 => "APM is supported.", + 11 => "BIOS is upgradeable (Flash).", + 12 => "BIOS shadowing is allowed.", + 13 => "VL-VESA is supported.", + 14 => "ESCD support is available.", + 15 => "Boot from CD is supported.", + 16 => "Selectable boot is supported.", + 17 => "BIOS ROM is socketed.", + 18 => "Boot from PC card (PCMCIA) is supported.", + 19 => "EDD specification is supported.", + 20 => "Japanese floppy for NEC 9800 1.2 MB (3.5”, 1K bytes/sector, 360 RPM) is supported.", + 21 => "Japanese floppy for Toshiba 1.2 MB (3.5”, 360 RPM) is supported.", + 22 => "5.25” / 360 KB floppy services are supported.", + 23 => "5.25” /1.2 MB floppy services are supported.", + 24 => "3.5” / 720 KB floppy services are supported.", + 25 => "3.5” / 2.88 MB floppy services are supported.", + 26 => "Print screen Service is supported.", + 27 => "8042 keyboard services are supported.", + 28 => "Serial services are supported.", + 29 => "Printer services are supported.", + 30 => "CGA/Mono Video Services are supported.", + 31 => "NEC PC-98." + ]; + + $defaultRegKeys = [ + "TdrLevel" => [3], + "NonBestEffortLimit" => [20], + "NetworkThrottlingIndex" => [10], + "EnableSuperfetch" => [null], + "DisableAntiVirus" => [0], + "DisableAntiSpyware" => [0], + "PUAProtection" => [0], + "PassiveMode" => [0], + "DontReportInfectionInformation" => [1], + "Disabled" => [0], + "AllowUpgradesWithUnsupportedTPMOrCPU" => [null], + "HwSchMode" => [1], + "UseWUServer" => [1], + "NoAutoUpdate" => [0], + "HiberbootEnabled" => [1], // side note, probably should be disabled cause bugs but eh its default + "AuditBoot" => [1], + "AllowBuildPreview" => [2], + "BypassCPUCheck" => [null], + "BypassStorageCheck" => [null], + "BypassRAMCheck" => [null], + "BypassTPMCheck" => [null], + "BypassSecureBootCheck" => [null], + "SV2" => [null], + "Win32PrioritySeparation" => [2], + "Windows Error Reporting\\Disabled" => [null], + "Windows Defender\\Passive Mode" => [null], + "UnsupportedHardwareNotificationCache\\SV2" => [null], + "HypervisorEnforcedCodeIntegrity" => [null], + ]; diff --git a/new/apps/web/src/php/manualupload.php b/new/apps/web/src/php/manualupload.php new file mode 100644 index 0000000..998d9fb --- /dev/null +++ b/new/apps/web/src/php/manualupload.php @@ -0,0 +1,61 @@ + $value) { + if(is_array($value) && is_array($arr2[$key])) { + if(check_keys_recursive($value, $arr2[$key])) { + return true; + } + } + else if(!(array_key_exists($key, $arr2))) { + return true; + } + } + } + + $extensions= array("json"); + +//In the interlink upload, we generate the filename by hashing two strings inside the json. +//In this method, I actually just straight up randomize the name entirely. + +//Don't ask why, it's fun. +//I don't expect this to hit entropy and filename clash with the other method or itself, given that files only have a lifespan of 24~ hours, we would have to have +//an insane amount of files being generated in a very short time span. + $randomBytes = random_bytes(4); + $randomString = bin2hex($randomBytes); + $randomString = preg_replace('/[^A-Za-z0-9]/', '', substr($randomString, 0, 8)); + + if(in_array($file_ext,$extensions)== false){ + $errors[]="Extension not allowed, please choose a Specify JSON file"; + } + + $json_data = json_decode(file_get_contents($file_tmp), true); + + if (check_keys_recursive($base, $json_data)) { + $errors[] = "Malformed JSON, please choose a Specify JSON file"; + } + + $file_name = $randomString.".json"; + + if(empty($errors)) { + move_uploaded_file($file_tmp,"files/".$file_name); + $pointer = 'profile/'.$randomString; + http_response_code(303); + header('Location: '.$pointer); + echo json_encode(array('redirecturl'=>$pointer)); + } + else{ + foreach($errors as $error){ + echo $error."\n"; + } + var_dump($_REQUEST); + } +?> \ No newline at end of file diff --git a/new/apps/web/src/php/phpstan.neon b/new/apps/web/src/php/phpstan.neon new file mode 100644 index 0000000..f483de6 --- /dev/null +++ b/new/apps/web/src/php/phpstan.neon @@ -0,0 +1,9 @@ +includes: + - vendor/phpstan/phpstan-strict-rules/rules.neon +parameters: + strictRules: + level: 0 + paths: + - . + excludePaths: + - 'vendor/' \ No newline at end of file diff --git a/new/apps/web/src/php/rudimentary.php b/new/apps/web/src/php/rudimentary.php new file mode 100644 index 0000000..2632621 --- /dev/null +++ b/new/apps/web/src/php/rudimentary.php @@ -0,0 +1,112 @@ + + + + + + Specify Archive + + + + + + + + + + + + + + +
+
+
+
+
'.$profile_name.'
+
+

'.date("F j, Y, g:i a",$ds).'
'.$json_data['Hardware']['Cpu']['Name'].'
'.$json_data['Hardware']['Gpu'][0]['Description'].'

+
+
+
'; +} +?> +
+
+ + + diff --git a/new/apps/web/src/php/static/css/backup.css b/new/apps/web/src/php/static/css/backup.css new file mode 100755 index 0000000..177c7be --- /dev/null +++ b/new/apps/web/src/php/static/css/backup.css @@ -0,0 +1,1071 @@ +@import url(https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;700&display=swap); + +html { + background-color: #3B4252!important; + color-scheme: dark +} + +body { + background-color: #3B4252!important; + color: #e0e2e4; + font-family: JetBrains Mono, monospace; + font-size: 10pt; + line-height: 150%; + margin: 0 +} + +body, html { + text-size-adjust: none; + -webkit-text-size-adjust: none; + -moz-text-size-adjust: none; + -ms-text-size-adjust: none +} + +main { + flex-grow: 1; + padding: 0 20px 20px +} + +#root, main { + display: flex; + flex-direction: column; + justify-content: space-between +} + +#root { + min-height: 100vh +} + +a:active, a:hover, a:link, a:visited { + color: #f77669; + text-decoration: none +} + +a:active, a:hover { + border-bottom: 1px solid #f77669 +} + +button, input, select { + background-color: #252b2d; + border-radius: 6px; + border-style: none; + color: #ccc; + font-family: JetBrains Mono, monospace; + padding: 5px +} + +button :focus, input :focus, select :focus { + outline: none +} + +select { + -webkit-appearance: none; + appearance: none; + background-image: url(data:image/svg+xml;base64,PHN2ZyBhcmlhLWhpZGRlbj0idHJ1ZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDQ4IDUxMiI+PHBhdGggZmlsbD0iI2I1YjViNSIgZD0iTTIwNy4wMjkgMzgxLjQ3NiAxMi42ODYgMTg3LjEzMmMtOS4zNzMtOS4zNzMtOS4zNzMtMjQuNTY5IDAtMzMuOTQxbDIyLjY2Ny0yMi42NjdjOS4zNTctOS4zNTcgMjQuNTIyLTkuMzc1IDMzLjkwMS0uMDRMMjI0IDI4NC41MDVsMTU0Ljc0NS0xNTQuMDIxYzkuMzc5LTkuMzM1IDI0LjU0NC05LjMxNyAzMy45MDEuMDRsMjIuNjY3IDIyLjY2N2M5LjM3MyA5LjM3MyA5LjM3MyAyNC41NjkgMCAzMy45NDFMMjQwLjk3MSAzODEuNDc2Yy05LjM3MyA5LjM3Mi0yNC41NjkgOS4zNzItMzMuOTQyIDB6Ii8+PC9zdmc+); + background-position: 97%; + background-repeat: no-repeat; + background-size: 10px +} + +button { + cursor: pointer +} + +hr { + border: 2px solid #252b2d +} + +.text-box { + background: #252b2d; + border-radius: 6px; + color: #b5b5b5; + font-size: 130%; + letter-spacing: -1px; + margin: 12px 0; + padding: 8px +} + +header { + background: #181d1f; + box-shadow: 0 0 4px #130b00; + color: #ccc; + font-weight: 400; + gap: 10px; + justify-content: space-between; + line-height: 100%; + margin: 0; + padding: 5px 20px; + z-index: 20 +} + +header, header > .logo { + align-items: center; + display: flex +} + +header > .logo { + background-color: #252b2d; + border: 0; + border-radius: 5px; + margin: 3px 0; + padding: 3px 5px 3px 3px +} + +header > .logo > h1 { + color: #fff; + font-size: 14pt; + font-weight: 400; + margin: 0; + padding: 0 3px +} + +header img { + -webkit-filter: invert(0); + filter: invert(0); + padding-right: 5px +} + +footer { + color: #888; + font-size: 10pt; + font-weight: 400; + margin-top: 30px; + padding: 0 20px 20px; + text-align: right +} + +article { + font-size: 120%; + margin: 20px auto; + max-width: 900px +} + +article h1:before, article h2:before { + color: #ffc93a; + content: "# " +} + +.homepage-header { + background: #181d1f; + display: flex; + justify-content: center +} + +.homepage-header > div { + display: flex; + flex-grow: 1; + justify-content: space-around; + max-width: 900px; + padding: 50px 0 +} + +.homepage-header > div > img { + width: 25% +} + +.homepage-header > div > div { + display: flex; + flex-direction: column; + justify-content: center; + text-align: center; + width: 60% +} + +.homepage-header > div > div > h1 { + font-size: min(15vw, 150px); + line-height: 1em; + margin: 0 0 15px +} + +.homepage-header > div > div > div { + font-size: min(2vw, 20px); + line-height: 1.1 +} + +.homepage .link { + height: 75px +} + +.homepage .link .link-description { + font-weight: 400; + width: 280px +} + +.homepage section { + background-color: #252b2d; + border-radius: 15px; + margin: 25px 0; + padding: .1px 15px +} + +.homepage .feature { + display: flex; + gap: 20px; + margin: 30px 0; + padding-left: 20px +} + +.homepage .feature > svg { + color: #7e7e7e; + font-size: 70px; + margin: auto 0 +} + +.homepage .feature > div { + max-width: 70% +} + +.homepage .feature > div h3 { + color: #ffc93a; + margin: 0 +} + +.downloads .version-number { + color: #f77669; + font-size: larger; + font-weight: 700 +} + +.downloads h3 > span { + color: #888; + font-size: 75% +} + +.downloads .link-description { + width: 250px +} + +.link { + align-items: center; + background-color: #252b2d; + border-radius: 15px; + display: flex; + gap: 15px; + height: 95px; + justify-content: space-between; + margin: 10px 0; + padding: 0 15px +} + +.link:link, .link:visited { + border-bottom: none; + color: #ccc +} + +.link:hover { + background-color: hsla(0, 0%, 61%, .1) +} + +.link .link-title { + align-items: center; + -webkit-column-gap: 15px; + column-gap: 15px; + display: flex; + flex-direction: row; + font-size: 150% +} + +.link .link-title svg { + color: #f77669; + font-size: 40px +} + +.link .link-description { + color: #7e7e7e +} + +.link .link-description code { + color: #ccc +} + +.file-picker { + border: 2px dashed; + cursor: pointer; + text-align: center +} + +.file-picker em { + font-size: 60% +} + +@import"https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;700&display=swap";:host,:root { + --fa-font-solid: normal 900 1em/1 "Font Awesome 6 Solid"; + --fa-font-regular: normal 400 1em/1 "Font Awesome 6 Regular"; + --fa-font-light: normal 300 1em/1 "Font Awesome 6 Light"; + --fa-font-thin: normal 100 1em/1 "Font Awesome 6 Thin"; + --fa-font-duotone: normal 900 1em/1 "Font Awesome 6 Duotone"; + --fa-font-sharp-solid: normal 900 1em/1 "Font Awesome 6 Sharp"; + --fa-font-brands: normal 400 1em/1 "Font Awesome 6 Brands" + } + +html { + background-color: #1e2527; + color-scheme: dark +} + +body { + font-family: JetBrains Mono,monospace; + font-size: 10pt; + line-height: 150%; + margin: 0; + color: #e0e2e4 +} + +body,html { + text-size-adjust: none; + -webkit-text-size-adjust: none; + -moz-text-size-adjust: none; + -ms-text-size-adjust: none +} + +main { + padding: 0 20px 20px; + flex-grow: 1 +} + +#__next,main { + display: flex; + flex-direction: column; + justify-content: space-between +} + +#__next { + min-height: 100vh +} + +a:active,a:hover,a:link,a:visited { + color: #f77669; + text-decoration: none +} + +a:active,a:hover { + border-bottom: 1px solid #f77669 +} + +button,input,select { + font-family: JetBrains Mono,monospace; + background-color: #252b2d; + border-style: none; + color: #ccc; + border-radius: 6px; + padding: 5px +} + +button :focus,input :focus,select :focus { + outline: none +} + +select { + -webkit-appearance: none; + appearance: none; + background-image: url(data:image/svg+xml;base64,PHN2ZyBhcmlhLWhpZGRlbj0idHJ1ZSIgZm9jdXNhYmxlPSJmYWxzZSIgcm9sZT0iaW1nIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48cGF0aCBmaWxsPSIjYjViNWI1IiBkPSJNMjA3LjAyOSAzODEuNDc2TDEyLjY4NiAxODcuMTMyYy05LjM3My05LjM3My05LjM3My0yNC41NjkgMC0zMy45NDFsMjIuNjY3LTIyLjY2N2M5LjM1Ny05LjM1NyAyNC41MjItOS4zNzUgMzMuOTAxLS4wNEwyMjQgMjg0LjUwNWwxNTQuNzQ1LTE1NC4wMjFjOS4zNzktOS4zMzUgMjQuNTQ0LTkuMzE3IDMzLjkwMS4wNGwyMi42NjcgMjIuNjY3YzkuMzczIDkuMzczIDkuMzczIDI0LjU2OSAwIDMzLjk0MUwyNDAuOTcxIDM4MS40NzZjLTkuMzczIDkuMzcyLTI0LjU2OSA5LjM3Mi0zMy45NDIgMHoiPjwvcGF0aD48L3N2Zz4=); + background-repeat: no-repeat; + background-position: 97%; + background-size: 10px +} + +button { + cursor: pointer +} + +hr { + border: 2px solid #252b2d +} + +article { + max-width: 900px; + margin: 20px auto; + font-size: 120% +} + +article h1:before,article h2:before { + content: "# "; + color: #ffc93a +} + +.textbox { + font-size: 130%; + letter-spacing: -1px; + color: #b5b5b5; + background: #252b2d; + padding: 8px; + margin: 12px 0; + border-radius: 6px +} + +.link { + background-color: #252b2d; + border-radius: 15px; + display: flex; + justify-content: space-between; + align-items: center; + gap: 15px; + height: 95px; + margin: 10px 0; + padding: 0 15px +} + +.link:link,.link:visited { + border-bottom: none; + color: #ccc +} + +.link:hover { + background-color: hsla(0,0%,61%,.1) +} + +.link svg { + color: #f77669; + font-size: 40px +} + +.link .link-title { + display: flex; + flex-direction: row; + align-items: center; + -webkit-column-gap: 15px; + column-gap: 15px; + font-size: 150% +} + +.link .link-description { + color: #7e7e7e +} + +.link .link-description code { + color: #ccc +} + +.footer_footer__kUwim { + color: #888; + margin-top: 30px; + padding: 0 20px 20px; + font-size: 10pt; + font-weight: 400; + text-align: right +} + +#header-header { + display: flex; + justify-content: space-between; + align-items: center; + gap: 10px; + background: #181d1f; + color: #ccc; + padding: 5px 20px; + margin: 0; + font-weight: 400; + box-shadow: 0 0 4px #130b00; + z-index: 20; + line-height: 100% +} + +#header-header>a { + display: flex; + align-items: center; + background-color: #252b2d; + border-radius: 5px; + padding: 3px 5px 3px 3px; + margin: 3px 0; + border: 0 +} + +#header-header>a>h1 { + padding: 0 3px; + font-size: 14pt; + margin: 0; + font-weight: 400; + color: #fff +} + +#header-header svg { + -webkit-filter: invert(0); + filter: invert(0); + padding-right: 5px +} + +.header-homepage { + background: #181d1f; + display: flex; + justify-content: center +} + +.header-homepage>div { + display: flex; + justify-content: space-around; + flex-grow: 1; + max-width: 900px; + padding: 50px 0 +} + +.header-homepage>div>svg { + width: 25% +} + +.header-homepage>div>div { + width: 60%; + display: flex; + flex-direction: column; + justify-content: center; + text-align: center +} + +.header-homepage>div>div>h1 { + font-size: min(15vw,150px); + line-height: 1em; + margin: 0 0 15px +} + +.header-homepage>div>div>div { + font-size: min(2vw,20px); + line-height: 1.1 +} +.sampler_sampler__BhYgT .stack { + margin-top: 20px; + padding-left: 10px +} + +.sampler_sampler__BhYgT .stack ul { + margin: 0; + padding: 0 0 0 20px +} + +.sampler_sampler__BhYgT .stack li { + margin: 0 0 0 -10px; + padding: 0; + list-style: none; + border-left: 1px solid #3c3f41 +} + +.sampler_sampler__BhYgT .stack li.parent { + border: 0 +} + +.sampler_sampler__BhYgT .stack .node-info { + display: flex; + width: 100%; + justify-content: space-between; + cursor: pointer +} + +.sampler_sampler__BhYgT .stack .node-info .time { + display: none; + position: absolute; + color: #888; + font-size: 90%; + padding: 0 4px; + white-space: normal +} + +.sampler_sampler__BhYgT .stack .node-info:hover { + background-color: #2e383e +} + +.sampler_sampler__BhYgT .stack .node-info:hover .time { + display: inline +} + +.sampler_sampler__BhYgT .stack .node-info:hover+ul { + background: #242b2f; + box-shadow: 0 2px 4px rgba(0,0,0,.4); + border-radius: 3px +} + +.sampler_sampler__BhYgT .stack .node-info.bookmarked { + box-shadow: inset 0 0 0 100vmax rgba(134,0,0,.5) +} + +.sampler_sampler__BhYgT .stack .name { + color: #bcbcbc; + background: url(data:image/svg+xml;base64,PHN2ZyBhcmlhLWhpZGRlbj0idHJ1ZSIgZm9jdXNhYmxlPSJmYWxzZSIgcm9sZT0iaW1nIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48cGF0aCBmaWxsPSIjYjViNWI1IiBkPSJNNDQ4IDgwdjM1MmMwIDI2LjUtMjEuNSA0OC00OCA0OEg0OGMtMjYuNSAwLTQ4LTIxLjUtNDgtNDhWODBjMC0yNi41IDIxLjUtNDggNDgtNDhoMzUyYzI2LjUgMCA0OCAyMS41IDQ4IDQ4ek05Mi41IDIyMC41bDEyMyAxMjNjNC43IDQuNyAxMi4zIDQuNyAxNyAwbDEyMy0xMjNjNy42LTcuNiAyLjItMjAuNS04LjUtMjAuNUgxMDFjLTEwLjcgMC0xNi4xIDEyLjktOC41IDIwLjV6Ij48L3BhdGg+PC9zdmc+) 0 no-repeat; + background-size: 8px; + background-position: 6px 50%; + padding-left: 20px; + white-space: nowrap +} + +.sampler_sampler__BhYgT .stack .collapsed .name { + background-image: url(data:image/svg+xml;base64,PHN2ZyBhcmlhLWhpZGRlbj0idHJ1ZSIgZm9jdXNhYmxlPSJmYWxzZSIgcm9sZT0iaW1nIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48cGF0aCBmaWxsPSIjYjViNWI1IiBkPSJNNDggMzJoMzUyYzI2LjUxIDAgNDggMjEuNDkgNDggNDh2MzUyYzAgMjYuNTEtMjEuNDkgNDgtNDggNDhINDhjLTI2LjUxIDAtNDgtMjEuNDktNDgtNDhWODBjMC0yNi41MSAyMS40OS00OCA0OC00OHptMTQwLjQ4NSAzNTUuNTE1bDEyMy4wMjktMTIzLjAyOWM0LjY4Ni00LjY4NiA0LjY4Ni0xMi4yODQgMC0xNi45NzFsLTEyMy4wMjktMTIzLjAzYy03LjU2LTcuNTYtMjAuNDg1LTIuMjA2LTIwLjQ4NSA4LjQ4NXYyNDYuMDU5YzAgMTAuNjkxIDEyLjkyNiAxNi4wNDUgMjAuNDg1IDguNDg2eiI+PC9wYXRoPjwvc3ZnPg==) +} + +.sampler_sampler__BhYgT .stack .lambda-part,.sampler_sampler__BhYgT .stack .native-part,.sampler_sampler__BhYgT .stack .package-part { + color: #5a5a5a +} + +.sampler_sampler__BhYgT .stack .lineNumber { + color: #5f5f5f; + padding-left: 2px +} + +.sampler_sampler__BhYgT .stack .remapped { + background: #293134; + border-radius: 3px; + padding: 0 2px +} + +.sampler_sampler__BhYgT .stack .percent { + color: #ffcd22; + font-size: 90%; + border-radius: 3px; + padding: 0 6px +} + +.sampler_sampler__BhYgT .stack .bar { + display: block; + min-width: 100px; + height: 15px; + margin-top: 2px; + margin-left: 20px; + border: 1px solid #484848; + background: #293134 +} + +.sampler_sampler__BhYgT .stack .bar .inner { + display: inline-block; + height: 15px; + background: #e2b671 +} + +@media screen and (max-width: 880px) { + .sampler_sampler__BhYgT .stack .bar { + display:none!important + } +} + +.sampler_sampler__BhYgT .sourceview .stack { + margin-bottom: 40px +} + +.sampler_sampler__BhYgT .sourceview .stack>li { + margin-left: 10px +} + +.sampler_sampler__BhYgT .sourceview .stack>h2>span { + font-size: 100%; + color: #888 +} + +.sampler_sampler__BhYgT .sourceview .other-sources { + padding-left: 10px +} + +.sampler_sampler__BhYgT .sourceview .other-sources li>span { + color: #888 +} + +.sampler_sampler__BhYgT .allview>.header,.sampler_sampler__BhYgT .flatview>.header,.sampler_sampler__BhYgT .graph>.header,.sampler_sampler__BhYgT .sourceview>.header { + margin: 0 10px; + max-width: 1000px; + font-size: 16px +} + +.sampler_sampler__BhYgT .allview>.header .button,.sampler_sampler__BhYgT .flatview>.header .button,.sampler_sampler__BhYgT .graph>.header .button,.sampler_sampler__BhYgT .sourceview>.header .button { + margin-left: 20px; + margin-bottom: 20px +} + +.sampler_sampler__BhYgT .allview>.header .button button,.sampler_sampler__BhYgT .flatview>.header .button button,.sampler_sampler__BhYgT .graph>.header .button button,.sampler_sampler__BhYgT .sourceview>.header .button button { + font-size: 16px; + padding-left: 10px; + padding-right: 10px +} + +.sampler_sampler__BhYgT .allview>.header .button button span,.sampler_sampler__BhYgT .flatview>.header .button button span,.sampler_sampler__BhYgT .graph>.header .button button span,.sampler_sampler__BhYgT .sourceview>.header .button button span { + color: #ffc93a +} + +.sampler_sampler__BhYgT .allview>.header .button p,.sampler_sampler__BhYgT .flatview>.header .button p,.sampler_sampler__BhYgT .graph>.header .button p,.sampler_sampler__BhYgT .sourceview>.header .button p { + margin: 5px 0; + font-weight: 300; + font-size: 14px; + color: #b5b5b5 +} + +.sampler_sampler__BhYgT .flame { + background-color: #252b2d; + padding: 20px; + box-sizing: border-box; + border-radius: .5rem +} + +.sampler_sampler__BhYgT .flame>div>div { + overflow-x: clip!important; + overflow-y: auto!important +} + +.sampler_sampler__BhYgT .flame .LabeledRect_div__3RSFb { + font-family: JetBrains Mono,monospace!important +} + +.sampler_sampler__BhYgT .flame .LabeledRect_rect__11W7H { + stroke: #181d1f!important +} + +.sampler_sampler__BhYgT .graph .VictoryContainer { + max-width: 1500px; + margin: 0 auto +} + +.sampler_sampler__BhYgT .graph .legend { + max-width: 1500px; + margin: 0 auto; + display: flex; + gap: 10px; + justify-content: center +} + +.sampler_sampler__BhYgT .graph .legend .button { + width: 150px; + cursor: pointer; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; + text-align: center +} + +.sampler_sampler__BhYgT .graph .legend .button.toggled { + font-weight: 700; + box-shadow: inset 0 -4px 0 #3c3f41 +} + +.sampler_sampler__BhYgT .no-results { + font-size: 130%; + color: maroon +} + + +.sampler_version-warning__7BkIx { + color: orange; + text-align: center +} + +.sampler_version-warning__7BkIx>svg { + float: right; + padding: 10px; + color: #b5b5b5; + cursor: pointer +} + +.widgets-widgets { + display: flex; + justify-content: space-evenly; + flex-wrap: wrap; + gap: 10px; + margin-bottom: 10px +} + +.widgets-widgets[data-hide=true] :nth-child(n+6) { + display: none +} + +@media screen and (max-width: 1450px) { + .widgets-widgets[data-hide=true] :nth-child(n+5) { + display:none + } +} + +@media screen and (max-width: 1160px) { + .widgets-widgets[data-hide=true] :nth-child(n+4) { + display:none + } +} + +@media screen and (max-width: 880px) { + .widgets-widgets[data-hide=true] :nth-child(n+3) { + display:none + } +} + +.widgets-widgets .widget { + color: #b5b5b5; + background: #252b2d; + padding: 2px 5px; + border-radius: 6px; + width: 260px; + max-width: 340px; + flex-grow: 1 +} + + +.widgets-widgets .widget h1 { + margin: 0; + padding-top: 5px; + padding-bottom: 8px; + font-size: 13pt; + font-weight: 400; + color: #fff; + text-align: center +} + +.widgets-widgets .widget h1 span { + vertical-align: middle; + padding-left: 6px; + font-size: 11pt; + color: #b5b5b5 +} + +.widgets-widgets .widget .widget-values { + display: flex +} + +.widgets-widgets .widget .widget-value { + display: flex; + flex-direction: column; + flex-grow: 1; + text-align: center +} + +.widgets-widgets .widget .widget-value div:first-child { + font-size: 16pt +} + +.widgets-widgets .widget .widget-value div:nth-child(2) { + color: #b5b5b5 +} + +.widgets-widgets .widget .widget-single-value { + display: flex; + justify-content: center +} + +.widgets-widgets .widget .widget-single-value span:nth-child(2) { + color: #b5b5b5; + padding: 0 5px +} + +.widgets-widgets .widget .widget-single-value span:first-child { + text-align: right +} + +.widgets-widgets .widget .widget-single-value span:nth-child(3) { + text-align: left +} + +.widgets-widgets .widget .widget-single-value span:nth-child(2n-1) { + flex-grow: 100; + flex-basis: 0 +} + +.expanded { + max-width: 1900px; + margin: auto +} + +.metadata-detail { + margin-top: 0 +} + +.metadata-detail p { + margin: 0 +} + +.metadata-detail p span { + color: #fff +} + +.metadata-detail .metadata-detail-controls { + padding: 0; + margin: 10px 0 30px +} + +.metadata-detail .metadata-detail-controls li { + list-style-type: none; + display: inline; + cursor: pointer; + margin: 0 3px; + background-color: #293134; + padding: 7px 15px; + border-radius: 5px +} + +.metadata-detail .metadata-detail-controls li.selected { + color: #fff +} + +.metadata-detail .metadata-detail-content>.configurations>p,.metadata-detail .metadata-detail-content>p { + margin: 0 5px +} + +.metadata-detail .configurations ul { + padding-left: 20px +} + +.metadata-detail .configurations ul ul { + border-left: 1px solid #3c3f41 +} + +.metadata-detail .configurations li { + list-style: none +} + +.metadata-detail .configurations .type-string { + color: #f7df97 +} + +.metadata-detail .configurations .type-boolean { + color: #78e6ff +} + +.metadata-detail .configurations .type-number { + color: #9bffa2 +} + +.metadata-detail .entity-counts { + display: flex; + justify-content: space-between; + -webkit-column-gap: 20px; + column-gap: 20px; + margin: 0 5px +} + +.metadata-detail .entity-counts>div { + width: 100% +} + +.metadata-detail .entity-counts .header { + background-color: #293134; + text-align: center; + padding: 5px; + border-radius: 5px; + margin-bottom: 10px +} + +.metadata-detail .entity-counts .header.region-selector { + display: flex; + justify-content: space-between +} + +.metadata-detail .entity-counts .button { + cursor: pointer; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; + padding: 0 5px +} + +.metadata-detail .entity-counts .detail-lists { + display: flex; + justify-content: space-between +} + +.metadata-detail .entity-counts .detail-lists>div { + width: 100%; + margin: 0 10px +} + +.metadata-detail .entity-counts .detail-lists ul { + margin-top: 5px; + list-style-type: none; + padding-left: 15px +} + +.metadata-detail .entity-counts .detail-lists span { + color: #fff +} + +.controls { + display: flex; + justify-content: space-between; + gap: 10px; + margin: 10px 0; + flex-wrap: wrap; + flex-basis: 1 +} + +.controls>div,.controls>input { + flex-grow: 1; + flex-shrink: 1; + height: 40px +} + +.controls .textbox { + padding: 0; + margin: 0 +} + +.controls .button { + max-width: 40px; + width: 40px; + cursor: pointer; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; + display: flex; + align-items: center; + justify-content: center +} + +.controls .button>svg { + padding: 0 5px +} + +.controls .button.toggled { + color: #fff; + box-shadow: inset 0 -3px 0 #3c3f41 +} + +.controls .sources-view-button { + justify-content: space-around; + max-width: 150px; + width: unset; + padding: 0 3px +} + +.controls .title { + text-align: center; + flex-grow: 2; + vertical-align: middle; + display: flex; + justify-content: center; + flex-direction: column; + min-height: 40px; + height: -webkit-fit-content; + height: -moz-fit-content; + height: fit-content +} + +.controls .title>span { + padding: 5px +} + +.controls .title img { + vertical-align: top; + padding-right: 3px +} + +.controls .searchbar { + flex-grow: 2; + padding: 0 0 0 28px; + background-image: url(data:image/svg+xml;base64,PHN2ZyBhcmlhLWhpZGRlbj0idHJ1ZSIgZm9jdXNhYmxlPSJmYWxzZSIgcm9sZT0iaW1nIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48cGF0aCBmaWxsPSIjYjViNWI1IiBkPSJNNTA1IDQ0Mi43TDQwNS4zIDM0M2MtNC41LTQuNS0xMC42LTctMTctN0gzNzJjMjcuNi0zNS4zIDQ0LTc5LjcgNDQtMTI4QzQxNiA5My4xIDMyMi45IDAgMjA4IDBTMCA5My4xIDAgMjA4czkzLjEgMjA4IDIwOCAyMDhjNDguMyAwIDkyLjctMTYuNCAxMjgtNDR2MTYuM2MwIDYuNCAyLjUgMTIuNSA3IDE3bDk5LjcgOTkuN2M5LjQgOS40IDI0LjYgOS40IDMzLjkgMGwyOC4zLTI4LjNjOS40LTkuNCA5LjQtMjQuNi4xLTM0ek0yMDggMzM2Yy03MC43IDAtMTI4LTU3LjItMTI4LTEyOCAwLTcwLjcgNTcuMi0xMjggMTI4LTEyOCA3MC43IDAgMTI4IDU3LjIgMTI4IDEyOCAwIDcwLjctNTcuMiAxMjgtMTI4IDEyOHoiPjwvcGF0aD48L3N2Zz4=); + background-repeat: no-repeat; + background-position: 8px; + background-size: 15px +} + +.hover{ + border-size: 5px; + border-style: solid; + border-color: transparent; +} +.hover:hover{ + transition-duration: 0.1s; + border-size: 5px; + border-style: solid; + border-color: #5E81AC; +} + +#pups{ + display:none; +} + +.json-data table{ + background:none; +} + +.accordion-button, .accordion-button:not(.collapsed) { + background: none; +} + +.accordion-button:hover { + background:#5E81AC; +} diff --git a/new/apps/web/src/php/static/css/doom-scroll.css b/new/apps/web/src/php/static/css/doom-scroll.css new file mode 100644 index 0000000..cdb7bef --- /dev/null +++ b/new/apps/web/src/php/static/css/doom-scroll.css @@ -0,0 +1,377 @@ +:root { + --bg-color: white; + --fg-color: black; + --line-color: hsl(0, 0%, 50%); + --link-color: #0969da; + + --progress-bar-filled: hsl(0, 0%, 70%); + --progress-bar-unfilled: hsl(0, 0%, 90%); + --progress-bar-color: var(--fg-color); + --table-alternate-color: hsl(0, 0%, 90%); + --nav-hover-color: hsl(0, 0%, 95%); + + + --green: #22c55e; + --yellow: #facc15; + --red: #ef4444; + --amd: rgb(215,27,27); + --intel: rgb(8,110,224); +} + +@media (prefers-color-scheme: dark) { + :root { + --bg-color: hsl(0, 0%, 13%); + --fg-color: #fefefe; + --line-color: hsl(0, 0%, 50%); + --link-color: #2f81f7; + + --progress-bar-filled: hsl(0, 0%, 30%); + --progress-bar-unfilled: hsl(0, 0%, 20%); + --progress-bar-color: var(--fg-color); + --table-alternate-color: hsl(0, 0%, 20%); + --nav-hover-color: hsl(0, 0%, 17%); + + + --green: #A3BE8C; + --yellow: rgb(235, 203, 139); + --red: rgb(191, 97, 106); + } +} + +:root { + color: var(--fg-color); + background-color: var(--bg-color); + font-family: "JetBrains Mono", monospace; +} + +.green { color: var(--green); } +.yellow { color: var(--yellow); } +.red { color: var(--red); } +.amd { color: var(--amd); } +.intel { color: var(--intel); } + +*, *::before, *::after { + box-sizing: border-box; +} + +body { + margin: 0; + display: flex; +} + +main { + width: 100%; + flex: 10 0 auto; /* allow horizontal scroll */ + margin: 1rem; +} + +nav { + position: sticky; + top: 0; + max-height: 100vh; + overflow-y: auto; + border-right: 1px solid var(--line-color); + padding-right: 1rem; + flex: 0 0 auto; +} + +#nav-collapse { + position: absolute; + right: 0; + display: inline-block; + margin-right: 0.5rem; +} + +#nav-expand { + display: none; +} + +.nav-collapsed #nav-list { + display: none; +} + +.nav-collapsed #nav-expand { + display: block; + position: relative; + left: 50%; + cursor: pointer; +} + +.nav-collapsed #nav-collapse { + display: none; +} + +.nav-space-below { + margin-bottom: 0.5rem; +} + +#nav-list { + margin-top: 0; /* We make it margin instead of padding so that it doesn't slide down when scrolling */ + padding-top: 1rem; + font-size: 16px; + list-style: none; + padding-left: 1rem; +} + +#nav-list li:hover { + background-color: var(--nav-hover-color); +} + +a { + color: var(--link-color); +} + +nav a { + text-decoration: none; + display: block; + width: 100%; +} + +/* this is just an empty element that ensures when you click on a heading, it scrolls to the left */ +.linker { + position: absolute; + left: 0; +} + +table { + border: 1px #595959 solid; + border-radius: 5px; + border-collapse: collapse; + table-layout: auto; +} + +tr:nth-child(even) { + background-color: var(--table-alternate-color); +} + +td, th { + font-size: 10pt; + font-weight: normal; + padding: 0.125rem 0.25rem; + border: 1px #595959 solid; +} + +th { + font-weight: bold; +} + +.nic tr > td:nth-child(2) { + min-width: 17ch; /* just to make it look nice, this is the width of a mac address with colons */ +} + +.td-center { + text-align: center; +} + + +.smart-table-wrapper { + display: flex; + gap: 1rem; +} + +#notes span { + font-weight: bold; +} + +/* + * MDB5 (modified) + * Version: FREE 7.1.0 + * + * + * Copyright: Material Design for Bootstrap + * https://mdbootstrap.com/ + * + * Read the license: https://mdbootstrap.com/general/license/ + */ +.progress, +.progress-stacked { + --mdb-progress-height: 4px; + --mdb-progress-font-size: 0.75rem; + --mdb-progress-bg: hsl(0, 0%, 80%); + --mdb-progress-border-radius: none; + --mdb-progress-box-shadow: none; + --mdb-progress-bar-color: #fff; + --mdb-progress-bar-bg: #3b71ca; + --mdb-progress-bar-transition: width 0.6s ease; + display: flex; + height: var(--mdb-progress-height); + overflow: hidden; + font-size: var(--mdb-progress-font-size); + background-color: var(--mdb-progress-bg); + border-radius: var(--mdb-progress-border-radius); + box-shadow: var(--mdb-progress-box-shadow); +} + +.progress-bar { + display: flex; + flex-direction: column; + justify-content: center; + overflow: hidden; + color: var(--mdb-progress-bar-color); + text-align: center; + white-space: nowrap; + background-color: var(--mdb-progress-bar-bg); + transition: var(--mdb-progress-bar-transition); +} +@media (prefers-reduced-motion: reduce) { + .progress-bar { + transition: none; + } +} + +.progress-bar-striped { + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: var(--mdb-progress-height) var(--mdb-progress-height); +} + +.progress-stacked > .progress { + overflow: visible; +} + +.progress-stacked > .progress > .progress-bar { + width: 100%; +} + +.progress-bar-animated { + animation: 1s linear infinite progress-bar-stripes; +} +@media (prefers-reduced-motion: reduce) { + .progress-bar-animated { + animation: none; + } +} +/* END MDB5 */ + +.progress { + border-radius: 0; + box-shadow: none; +} + +.partition-whole-bar { + height: 64px; + background-color: inherit; + border: 2px #595959 solid; + margin-bottom: 0.5rem; +} + +.partition-one-bar { + background-color: var(--progress-bar-unfilled); + border-right: 2px #595959 solid; + position: relative; + height: 100%; +} + +.partition-space-bar { + height: 100%; + background-color: var(--progress-bar-filled); +} + +.partition-bar-label { + position: absolute; + left: 50%; + transform: translateX(-50%); + color: var(--progress-bar-color); +} + +.smart-table-wrapper { + column-count: 2; +} + +pre { + border: 1px solid var(--line-color); + padding: 2px; +} + +pre code { + font-family: "JetBrains Mono", monospace; + font-size: 13px; + counter-reset: line; +} + +pre code span { + display: block; + counter-increment: line; +} + +#debug-log { + display: none; +} + +/** +From PrismJS: https://github.com/PrismJS/prism/blob/master/LICENSE + */ +.file code span:before { + content: counter(line); + display: inline-block; + text-align: right; + pointer-events: none; + top: 0; + font-size: 100%; + left: -3.8em; + width: 2em; + letter-spacing: -1px; + color: var(--line-color); + border-right: 1px solid var(--line-color); + padding-right: 0.5em; + margin-right: 0.5em; + + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.machinecheck-exception:not(:last-child) { + margin-bottom: 1rem; +} + +.whea-packets { + display: grid; + grid-template-columns: repeat(2, 1fr); + row-gap: 1rem; + column-gap: 0.5rem; +} + +/* https://www.w3schools.com/tags/tag_hn.asp */ +.whea-summary { + /*display: block;*/ + font-size: 1em; + margin-top: 1.33em; + margin-bottom: 1.33em; + margin-left: 0; + margin-right: 0; + font-weight: bold; +} + +.whea-summary:hover { + cursor: pointer; +} + +.whea-row { + display: flex; + flex-direction: row; + align-items: stretch; + gap: 0.5rem; +} + +/* I want the columns of the table to line up and idk any better way to do it than this */ +.whea-descriptor td:first-child { + width: 20ch; +} + +.whea-packet { + margin: 0; +} + +.tr-focus { + border: 2px solid var(--link-color); +} + +.hidden { + display: none; +} + +/* We already have our own No Data message */ +.dataTables_empty { + display: none; +} diff --git a/new/apps/web/src/php/static/css/landing.css b/new/apps/web/src/php/static/css/landing.css new file mode 100755 index 0000000..0521965 --- /dev/null +++ b/new/apps/web/src/php/static/css/landing.css @@ -0,0 +1,69 @@ +.homepage-homepage section { + background-color: #252b2d; + border-radius: 15px; + margin: 25px 0; + padding: .1px 15px +} + +.homepage-homepage .link .link-description { + width: 17.5rem; + font-weight: 400 +} + +@media (max-width: 640px) { + .homepage-homepage .link { + flex-direction: column; + align-items: start; + height: auto; + padding-bottom: .75rem; + gap: .5rem + } + + .homepage-homepage .link .link-description { + width: auto; + margin-bottom: .5rem + } +} + +.homepage-homepage .feature { + display: flex; + gap: 20px; + padding-left: 20px; + margin: 30px 0 +} + +.homepage-homepage .feature > div { + max-width: 70% +} + +.homepage-homepage .feature > div h3 { + margin: 0; + color: #ffc93a +} + +.file-picker { + text-align: center; + cursor: pointer; + border: 2px dashed; + width: 100%; +} +.file-picker:hover{ + transition : border 500ms ease-out; + border-color: red; +} +.hoverBox{ + transition : border 500ms ease-out; + border-color: red; +} +.file-picker em { + font-size: 60% +} +h2 { + display: block; + font-size: 1.5em; + margin-block-start: 0.83em; + margin-block-end: 0.83em; + margin-inline-start: 0px; + margin-inline-end: 0px; + font-weight: bold; +} \ No newline at end of file diff --git a/new/apps/web/src/php/static/css/main.css b/new/apps/web/src/php/static/css/main.css new file mode 100755 index 0000000..80bcbdb --- /dev/null +++ b/new/apps/web/src/php/static/css/main.css @@ -0,0 +1,1052 @@ +@import url(https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;700&display=swap); + +html { + background-color: var(--bg-color); + color-scheme: var(--color-scheme); +} + +body { + background-color: var(--bg-color); + color: var(--fg-color); + font-family: JetBrains Mono, monospace; + font-size: 10pt; + line-height: 150%; + margin: 0; +} + +body, +html { + text-size-adjust: none; + -webkit-text-size-adjust: none; + -moz-text-size-adjust: none; + -ms-text-size-adjust: none; +} + +main { + flex-grow: 1; + padding: 0 20px 20px; +} + +#root, +main { + display: flex; + flex-direction: column; + justify-content: space-between; +} + +#root { + min-height: 100vh; +} + +a:active, +a:hover, +a:link, +a:visited { + color: #f77669; + text-decoration: none; +} + +a:active, +a:hover { + border-bottom: 1px solid #f77669; +} + +button, +input, +select { + background-color: var(--secondary-bg); + border-radius: 6px; + border-style: none; + color: #ccc; + font-family: JetBrains Mono, monospace; + padding: 5px; +} + +button :focus, +input :focus, +select :focus { + outline: none; +} + +select { + -webkit-appearance: none; + appearance: none; + background-image: url(data:image/svg+xml;base64,PHN2ZyBhcmlhLWhpZGRlbj0idHJ1ZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDQ4IDUxMiI+PHBhdGggZmlsbD0iI2I1YjViNSIgZD0iTTIwNy4wMjkgMzgxLjQ3NiAxMi42ODYgMTg3LjEzMmMtOS4zNzMtOS4zNzMtOS4zNzMtMjQuNTY5IDAtMzMuOTQxbDIyLjY2Ny0yMi42NjdjOS4zNTctOS4zNTcgMjQuNTIyLTkuMzc1IDMzLjkwMS0uMDRMMjI0IDI4NC41MDVsMTU0Ljc0NS0xNTQuMDIxYzkuMzc5LTkuMzM1IDI0LjU0NC05LjMxNyAzMy45MDEuMDRsMjIuNjY3IDIyLjY2N2M5LjM3MyA5LjM3MyA5LjM3MyAyNC41NjkgMCAzMy45NDFMMjQwLjk3MSAzODEuNDc2Yy05LjM3MyA5LjM3Mi0yNC41NjkgOS4zNzItMzMuOTQyIDB6Ii8+PC9zdmc+); + background-position: 97%; + background-repeat: no-repeat; + background-size: 10px; + padding-right: 20px; +} + +button { + cursor: pointer; +} + +hr { + border: 2px solid #252b2d; +} + +header { + background: #181d1f; + box-shadow: 0 0 4px #130b00; + color: #ccc; + font-weight: 400; + gap: 10px; + justify-content: space-between; + line-height: 100%; + margin: 0; + padding: 5px 20px; + z-index: 20; +} + +header, +header > #header-logo > .logo { + align-content: center; + justify-content: center; +} + +header > #header-logo > .logo { + background-color: var(--logo-bg); + border: 0; + border-radius: 5px; + padding: 6px 3px; +} + +header > #header-logo > .logo > h1 { + color: #fff; + font-size: 14pt; + font-weight: 400; + margin: 0; + padding: 0 3px; +} + +header img { + -webkit-filter: invert(0); + filter: invert(0); + padding-right: 5px; + align-self: center; +} + +header > #header-logo > .logo img { + padding: 0; +} + +/* this is only used in landing as of 2024-03-31 */ +footer { + color: #888; + font-size: 10pt; + font-weight: 400; + margin-top: 30px; + padding: 0 20px 20px; + text-align: right; +} + +/* this is only used in landing as of 2024-03-31 */ +article { + font-size: 120%; + margin: 20px auto; + max-width: 900px; +} + +article h1:before, +article h2:before { + color: #ffc93a; + content: "# "; +} + +optgroup { + width: auto; + font-style: normal; +} + +.homepage-header > div { + display: flex; + flex-grow: 1; + justify-content: space-around; + max-width: 900px; + padding: 50px 0; +} + +.homepage-header > div > img { + width: 25%; +} + +.homepage-header > div > div { + display: flex; + flex-direction: column; + justify-content: center; + text-align: center; + width: 60%; +} + +.homepage-header > div > div > h1 { + font-size: min(15vw, 150px); + line-height: 1em; + margin: 0 0 15px; +} + +.homepage-header > div > div > div { + font-size: min(2vw, 20px); + line-height: 1.1; +} + +.homepage .link { + height: 75px; +} + +.homepage .link .link-description { + font-weight: 400; + width: 280px; +} + +.homepage section { + background-color: #252b2d; + border-radius: 15px; + margin: 25px 0; + padding: 0.1px 15px; +} + +.homepage .feature { + display: flex; + gap: 20px; + margin: 30px 0; + padding-left: 20px; +} + +.homepage .feature > svg { + color: #7e7e7e; + font-size: 70px; + margin: auto 0; +} + +.homepage .feature > div { + max-width: 70%; +} + +.homepage .feature > div h3 { + color: #ffc93a; + margin: 0; +} + +.downloads h3 > span { + color: #888; + font-size: 75%; +} + +.downloads .link-description { + width: 250px; +} + +/* this is only used in homepage used as of 2024-03-31 */ +.link { + align-items: center; + background-color: #252b2d; + border-radius: 15px; + display: flex; + gap: 15px; + height: 95px; + justify-content: space-between; + margin: 10px 0; + padding: 0 15px; +} + +.link:link, +.link:visited { + border-bottom: none; + color: #ccc; +} + +.link:hover { + background-color: hsla(0, 0%, 61%, 0.1); +} + +.link .link-title { + align-items: center; + -webkit-column-gap: 15px; + column-gap: 15px; + display: flex; + flex-direction: row; + font-size: 150%; +} + +.link .link-title svg { + color: #f77669; + font-size: 40px; +} + +.link .link-description { + color: #7e7e7e; +} + +.link .link-description code { + color: #ccc; +} + +.file-picker em { + font-size: 60%; +} + +@import "https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;700&display=swap"; +:host, +:root { + --fa-font-solid: normal 900 1em/1 "Font Awesome 6 Solid"; + --fa-font-regular: normal 400 1em/1 "Font Awesome 6 Regular"; + --fa-font-light: normal 300 1em/1 "Font Awesome 6 Light"; + --fa-font-thin: normal 100 1em/1 "Font Awesome 6 Thin"; + --fa-font-duotone: normal 900 1em/1 "Font Awesome 6 Duotone"; + --fa-font-sharp-solid: normal 900 1em/1 "Font Awesome 6 Sharp"; + --fa-font-brands: normal 400 1em/1 "Font Awesome 6 Brands"; +} + +body { + font-family: JetBrains Mono, monospace; + font-size: 10pt; + line-height: 150%; + margin: 0; +} + +body, +html { + text-size-adjust: none; + -webkit-text-size-adjust: none; + -moz-text-size-adjust: none; + -ms-text-size-adjust: none; +} + +main { + padding: 0 20px 20px; + flex-grow: 1; +} + +#__next, +main { + display: flex; + flex-direction: column; + justify-content: space-between; +} + +#__next { + min-height: 100vh; +} + +a:active, +a:hover, +a:link, +a:visited { + color: var(--link-secondary); + text-decoration: none; +} + +a:active, +a:hover { + border-bottom: 1px solid var(--link-secondary); +} + +button, +input, +select { + font-family: JetBrains Mono, monospace; + background-color: var(--secondary-bg); + border-style: none; + color: var(--button-fg); + border-radius: 6px; + padding: 5px; +} + +button :focus, +input :focus, +select :focus { + outline: none; +} + +select { + -webkit-appearance: none; + appearance: none; + background-image: url(data:image/svg+xml;base64,PHN2ZyBhcmlhLWhpZGRlbj0idHJ1ZSIgZm9jdXNhYmxlPSJmYWxzZSIgcm9sZT0iaW1nIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA0NDggNTEyIj48cGF0aCBmaWxsPSIjYjViNWI1IiBkPSJNMjA3LjAyOSAzODEuNDc2TDEyLjY4NiAxODcuMTMyYy05LjM3My05LjM3My05LjM3My0yNC41NjkgMC0zMy45NDFsMjIuNjY3LTIyLjY2N2M5LjM1Ny05LjM1NyAyNC41MjItOS4zNzUgMzMuOTAxLS4wNEwyMjQgMjg0LjUwNWwxNTQuNzQ1LTE1NC4wMjFjOS4zNzktOS4zMzUgMjQuNTQ0LTkuMzE3IDMzLjkwMS4wNGwyMi42NjcgMjIuNjY3YzkuMzczIDkuMzczIDkuMzczIDI0LjU2OSAwIDMzLjk0MUwyNDAuOTcxIDM4MS40NzZjLTkuMzczIDkuMzcyLTI0LjU2OSA5LjM3Mi0zMy45NDIgMHoiPjwvcGF0aD48L3N2Zz4=); + background-repeat: no-repeat; + background-position: 97%; + background-size: 10px; +} + +button { + cursor: pointer; +} + +/* not used in viewer (may be used elsewhere) as of 2024-03-31 */ +hr { + border: 2px solid #252b2d; +} + +/* not used in viewer (may be used elsewhere) as of 2024-03-31 */ +article { + max-width: 900px; + margin: 20px auto; + font-size: 120%; +} + +/* not used in viewer (may be used elsewhere) as of 2024-03-31 */ +article h1:before, +article h2:before { + content: "# "; + color: #ebcb8b; +} + +.textbox { + font-size: 130%; + letter-spacing: -1px; + color: var(--secondary-fg); + background: var(--secondary-bg); + padding: 8px; + margin: 12px 0; + border-radius: 6px; +} + +.tablebox { + overflow: scroll; + padding-top: 1rem; +} + +.dataTables_wrapper > div { + margin: 0; +} + +.tabbed-info { + padding: 24px; +} + +/* not used in viewer (may be used elsewhere) as of 2024-03-31 */ +.link { + background-color: #252b2d; + border-radius: 15px; + display: flex; + justify-content: space-between; + align-items: center; + gap: 15px; + height: 95px; + margin: 10px 0; + padding: 0 15px; +} + +.link:link, +.link:visited { + border-bottom: none; + color: #ccc; +} + +.link:hover { + background-color: hsla(0, 0%, 61%, 0.1); +} + +.link svg { + color: #f77669; + font-size: 40px; +} + +.link .link-title { + display: flex; + flex-direction: row; + align-items: center; + -webkit-column-gap: 15px; + column-gap: 15px; + font-size: 150%; +} + +.link .link-description { + color: #7e7e7e; +} + +.link .link-description code { + color: #ccc; +} + +#header-header { + display: flex; + justify-content: space-between; + align-items: center; + gap: 10px; + background: var(--header-bg); + /*color: #ccc;*/ + padding: 5px 20px; + margin: 0; + font-weight: 400; + box-shadow: 0 0 4px var(--box-shadow); + z-index: 20; + line-height: 100%; +} + +#header-header > #header-logo > a { + align-self: center; + background-color: var(--logo-bg); + border-radius: 5px; + padding: 6px 3px; + border: 0; + display: inline-flex; +} + +#header-header > :first-child, #header-header > :last-child { + flex-grow: 1; + flex-basis: 0; +} + +#style-toggles { + display: flex; + justify-content: flex-end; + flex-wrap: wrap; + gap: 8px; +} + +#header-buttons { + display: flex; + gap: 8px; + flex-flow: wrap; + justify-content: center; +} + +#header-header select > option { + background-color: var(--header-dropdown); +} + +/* not used in viewer (may be used elsewhere) as of 2024-03-31 */ +#header-header > a > h1 { + padding: 0 3px; + font-size: 14pt; + margin: 0; + font-weight: 400; + color: #fff; +} + +/* not used in viewer (may be used elsewhere) as of 2024-03-31 */ +#header-header svg { + -webkit-filter: invert(0); + filter: invert(0); + padding-right: 5px; +} + +.header-homepage { + background: #181d1f; + display: flex; + justify-content: center; +} + +.header-homepage > div { + display: flex; + justify-content: space-around; + flex-grow: 1; + max-width: 900px; + padding: 50px 0; +} + +.header-homepage > div > svg { + width: 25%; +} + +.header-homepage > div > div { + width: 60%; + display: flex; + flex-direction: column; + justify-content: center; + text-align: center; +} + +.header-homepage > div > div > h1 { + font-size: min(15vw, 150px); + line-height: 1em; + margin: 0 0 15px; +} + +.header-homepage > div > div > div { + font-size: min(2vw, 20px); + line-height: 1.1; +} + +@media screen and (max-width: 880px) { +} + +.sampler_version-warning__7BkIx > svg { + float: right; + padding: 10px; + color: #b5b5b5; + cursor: pointer; +} + +.widgets-widgets { + display: flex; + justify-content: space-evenly; + flex-wrap: wrap; + gap: 10px; + margin-bottom: 10px; +} + +.widgets-widgets[data-hide="true"] :nth-child(n + 6) { + display: none; +} + +@media screen and (max-width: 1450px) { + .widgets-widgets[data-hide="true"] :nth-child(n + 5) { + display: none; + } +} + +@media screen and (max-width: 1160px) { + .widgets-widgets[data-hide="true"] :nth-child(n + 4) { + display: none; + } +} + +@media screen and (max-width: 880px) { + .widgets-widgets[data-hide="true"] :nth-child(n + 3) { + display: none; + } +} + +.widgets-widgets .widget { + color: var(--secondary-fg); + background: var(--secondary-bg); + padding: 2px 5px; + border-radius: 6px; + width: 260px; + max-width: 340px; + flex-grow: 1; +} + +.widgets-widgets .widget h1 { + margin: 0; + padding-top: 5px; + padding-bottom: 8px; + font-size: 13pt; + font-weight: 400; + color: var(--widget-emph); + text-align: center; +} + +.widgets-widgets .widget h1 span { + vertical-align: middle; + padding-left: 6px; + font-size: 11pt; + color: var(--secondary-fg); +} + +.widgets-widgets .widget .widget-values { + display: flex; +} + +.widgets-widgets .widget .widget-value { + display: flex; + flex-direction: column; + flex-grow: 1; + text-align: center; +} + +.widgets-widgets .widget .widget-value div:first-child { + font-size: 16pt; +} + +.widgets-widgets .widget .widget-value div:nth-child(2) { + color: var(--secondary-fg); +} + +.widgets-widgets .widget .widget-single-value { + display: flex; + justify-content: center; +} + +.widgets-widgets .widget .widget-single-value span:nth-child(2) { + color: var(--secondary-fg); + padding: 0 5px; +} + +.widgets-widgets .widget .widget-single-value span:first-child { + text-align: right; +} + +.widgets-widgets .widget .widget-single-value span:nth-child(3) { + text-align: left; +} + +.widgets-widgets .widget .widget-single-value span:nth-child(2n-1) { + flex-grow: 100; + flex-basis: 0; +} + +.metadata-metadata .metadata-detail { + margin-top: 0; +} + +.metadata-metadata .metadata-detail p { + margin: 0; +} + +.metadata-metadata .metadata-detail p span { + color: var(--widget-emph); +} + +.metadata-metadata .metadata-detail .metadata-detail-controls { + padding: 0; + margin: 10px 0 15px; +} +/* +.metadata-metadata .metadata-detail .metadata-detail-controls li { + list-style-type: none; + display: inline; + cursor: pointer; + margin: 0 3px; + background-color: #293134; + padding: 7px 15px; + border-radius: 5px; +} + +.metadata-metadata .metadata-detail .metadata-detail-controls li.selected { + color: #fff; +} */ + +.metadata-metadata .metadata-detail .metadata-detail-controls button { + list-style-type: none; + display: inline; + cursor: pointer; + margin: 0 3px; + margin-bottom: 5px; + background-color: var(--tertiary-bg); + padding: 7px 15px; + border-radius: 5px; +} + +.metadata-metadata .metadata-detail .metadata-detail-controls button.selected { + color: var(--widget-emph); +} + +.metadata-metadata + .metadata-detail + .metadata-detail-content + > .configurations + > p, +.metadata-metadata .metadata-detail .metadata-detail-content > p { + margin: 0 5px; +} + +.metadata-metadata .metadata-detail .configurations ul { + padding-left: 20px; +} + +/* not used in viewer (may be used elsewhere) as of 2024-03-31 */ +.metadata-metadata .metadata-detail .configurations ul ul { + border-left: 1px solid #3c3f41; +} + +.metadata-metadata .metadata-detail .configurations li { + list-style: none; +} + +.metadata-metadata .metadata-detail .entity-counts > div { + width: 100%; +} + +.metadata-metadata .metadata-detail .entity-counts .button { + cursor: pointer; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; + padding: 0 5px; +} + +.metadata-metadata .metadata-detail .entity-counts .detail-lists > div { + width: 100%; + margin: 0 10px; +} + +.metadata-metadata .metadata-detail .entity-counts .detail-lists ul { + margin-top: 5px; + list-style-type: none; + padding-left: 15px; +} + +.metadata-metadata .metadata-detail .entity-counts .detail-lists span { + color: #fff; +} + +.controls { + display: flex; + justify-content: space-between; + gap: 10px; + margin: 10px 0; + flex-wrap: wrap; + flex-basis: 1; +} + +.controls > div, +.controls > input { + flex-grow: 1; + flex-shrink: 1; + height: 40px; +} + +.controls .textbox { + padding: 0; + margin: 0; +} + +.controls .button { + max-width: 40px; + width: 40px; + cursor: pointer; + -webkit-user-select: none; + -ms-user-select: none; + user-select: none; + display: flex; + align-items: center; + justify-content: center; +} + +.controls .button > svg { + padding: 0 5px; +} + +.controls .title { + text-align: center; + flex-grow: 2; + vertical-align: middle; + display: flex; + justify-content: center; + flex-direction: column; + min-height: 40px; + height: -webkit-fit-content; + height: -moz-fit-content; + height: fit-content; +} + +.controls .title > span { + padding: 5px; +} + +.controls .title img { + vertical-align: top; + padding-right: 3px; +} + +.controls .searchbar { + flex-grow: 2; + padding: 0 0 0 28px; + background-image: url(data:image/svg+xml;base64,PHN2ZyBhcmlhLWhpZGRlbj0idHJ1ZSIgZm9jdXNhYmxlPSJmYWxzZSIgcm9sZT0iaW1nIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48cGF0aCBmaWxsPSIjYjViNWI1IiBkPSJNNTA1IDQ0Mi43TDQwNS4zIDM0M2MtNC41LTQuNS0xMC42LTctMTctN0gzNzJjMjcuNi0zNS4zIDQ0LTc5LjcgNDQtMTI4QzQxNiA5My4xIDMyMi45IDAgMjA4IDBTMCA5My4xIDAgMjA4czkzLjEgMjA4IDIwOCAyMDhjNDguMyAwIDkyLjctMTYuNCAxMjgtNDR2MTYuM2MwIDYuNCAyLjUgMTIuNSA3IDE3bDk5LjcgOTkuN2M5LjQgOS40IDI0LjYgOS40IDMzLjkgMGwyOC4zLTI4LjNjOS40LTkuNCA5LjQtMjQuNi4xLTM0ek0yMDggMzM2Yy03MC43IDAtMTI4LTU3LjItMTI4LTEyOCAwLTcwLjcgNTcuMi0xMjggMTI4LTEyOCA3MC43IDAgMTI4IDU3LjIgMTI4IDEyOCAwIDcwLjctNTcuMiAxMjgtMTI4IDEyOHoiPjwvcGF0aD48L3N2Zz4=); + background-repeat: no-repeat; + background-position: 8px; + background-size: 15px; +} + +.hover { + border-size: 5px; + border-style: solid; + border-color: transparent; +} +.hover:hover { + transition-duration: 0.1s; + border-size: 5px; + border-style: solid; + border-color: var(--select-color); +} + +/* not used in viewer (may be used elsewhere) as of 2024-03-31 */ +.drive-span:hover { + color: #ffffffbf !important; +} + +#pups { + display: none; +} +#variables { + display: none; +} +#browsers { + display: none; +} +#startup { + display: none; +} +#updates { + display: none; +} + +.accordion-button { + background: none !important; + color: var(--widget-emph) !important; +} +.accordion-button:hover { + background: var(--select-color) !important; +} +.center { + display: block; + margin-left: auto; + margin-right: auto; +} + +#btn-back-to-top { + position: fixed; + bottom: 20px; + right: 20px; + z-index: 999; + + opacity: 0; + visibility: hidden; + + transition: opacity 0.1s ease-in; + will-change: opacity, visibility; +} + +#btn-back-to-top svg { + height: 20px; +} + +#archive { + margin: auto; + width: 80%; +} +#login-form { + background-color: #2e383e; + width: 20%; + position: absolute; + left: 50%; + top: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); +} + +/* initial property, will be changed when the button is clicked */ +#collapse-toggle-hide { + display: none; +} + +#download:hover { + text-decoration: none; + border-bottom: none; +} + +.even { + background-color: var(--tr-even); +} + +.previous { + margin-left: auto; +} + +.form-control { + width: auto; + margin-left: 1rem; + display: inline-block; +} + +.form-select { + width: auto; + display: inline-block; +} + +label { + font-size: 10pt; +} + +table { + border: 1px var(--border-color) solid; + border-radius: 5px; + border-collapse: collapse; +} + +.table td, +.table th { + font-size: 10pt; + font-weight: normal; + padding: 0.125rem 0.25rem; + border: 1px var(--border-color) solid; +} + +.table > :not(:last-child) > :last-child > * { + border-bottom-color: var(--border-color); +} + +.json-data table { + background: none; +} + +.table { + table-layout: auto; + color: var(--table-color); + background: transparent; +} + +.nic { + width: 50%; + display: inline-block; + margin: auto; +} + +.nic td:not(:first-child){ + width: 100%; +} + +.dataTables_info { + font-size: 10pt; + padding-left: 0.5rem; +} + +.dataTables_length { + margin-bottom: 0.5rem; +} + +.dataTables_filter { + float: right; +} + +#blanket{ + display:none; + width:100%; + height:100%; + position:fixed; + top:0px; + left:0px; + z-index:9999; + background-color:black; +} + +.modal-content { + background-color: var(--modal-color); +} + +.modal-column { + float: left; +} + +.modal-column:not(:first-of-type) { + margin-left: 1rem; +} + +.smart-table-wrapper { + display: flex; + gap: 1rem; +} + +.partition-whole-bar { + height: 64px; + background-color: inherit; + border: 2px var(--border-color) solid; + margin-bottom: 0.5rem; +} + +.partition-one-bar { + background-color: inherit; + border-right: 2px var(--border-color) solid; + position: relative; + height: 100%; +} + +.partition-space-bar { + height: 100%; + background-color: var(--partition-bar-filled); +} + +.partition-bar-label { + position: absolute; + left: 50%; + transform: translateX(-50%); +} + +.green { color: var(--green) !important; } +.yellow { color: var(--yellow) !important; } +.red { color: var(--red) !important; } +.amd { color: var(--amd) !important; } +.intel { color: var(--intel) !important; } diff --git a/new/apps/web/src/php/static/css/tables.css b/new/apps/web/src/php/static/css/tables.css new file mode 100644 index 0000000..5ebd0d0 --- /dev/null +++ b/new/apps/web/src/php/static/css/tables.css @@ -0,0 +1,95 @@ +/* + +MODIFIED DATATABLES CSS - MIT LICENSE + +Copyright (C) 2008-2023, SpryMedia Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +*/ + +table.dataTable thead > tr > th.sorting, +table.dataTable thead > tr > th.sorting_asc, +table.dataTable thead > tr > th.sorting_desc { + cursor: pointer; + position: relative; + padding-right: 26px; +} + +table.dataTable thead > tr > th.sorting:before, +table.dataTable thead > tr > th.sorting:after, +table.dataTable thead > tr > th.sorting_asc:before, +table.dataTable thead > tr > th.sorting_asc:after, +table.dataTable thead > tr > th.sorting_desc:before, +table.dataTable thead > tr > th.sorting_desc:after { + position: absolute; + display: block; + opacity: 0.125; + right: 10px; + line-height: 9px; + font-size: 0.8em; +} + +table.dataTable thead > tr > th.sorting:before, +table.dataTable thead > tr > th.sorting_asc:before, +table.dataTable thead > tr > th.sorting_desc:before{ + bottom: 50%; + content: "▲"; + content: "▲"/""; +} + +table.dataTable thead > tr > th.sorting:after, +table.dataTable thead > tr > th.sorting_asc:after, +table.dataTable thead > tr > th.sorting_desc:after{ + top: 50%; + content: "▼"; + content: "▼"/""; +} + +table.dataTable thead > tr > th.sorting_asc:before, +table.dataTable thead > tr > th.sorting_desc:after, +table.dataTable thead > tr > td.sorting_asc:before, +table.dataTable thead > tr > td.sorting_desc:after { + opacity: 0.6; +} + +table.dataTable thead > tr > th:active, +table.dataTable thead > tr > td:active { + outline: none; +} + +table.dataTable td.dt-control { + text-align: center; + cursor: pointer; +} +table.dataTable td.dt-control:before { + display: inline-block; + box-sizing: border-box; + content: ""; + border-top: 5px solid transparent; + border-left: 10px solid var(--border-color); + border-bottom: 5px solid transparent; + border-right: 0px solid transparent; +} +table.dataTable tr.dt-hasChild td.dt-control:before { + border-top: 10px solid var(--border-color); + border-left: 5px solid transparent; + border-bottom: 0px solid transparent; + border-right: 5px solid transparent; +} + +html.dark table.dataTable td.dt-control:before, +:root[data-bs-theme=dark] table.dataTable td.dt-control:before, +:root[data-theme=dark] table.dataTable td.dt-control:before { + border-left-color: var(--border-color); +} +html.dark table.dataTable tr.dt-hasChild td.dt-control:before, +:root[data-bs-theme=dark] table.dataTable tr.dt-hasChild td.dt-control:before, +:root[data-theme=dark] table.dataTable tr.dt-hasChild td.dt-control:before { + border-top-color: var(--border-color); + border-left-color: transparent; +} \ No newline at end of file diff --git a/new/apps/web/src/php/static/css/themes.css b/new/apps/web/src/php/static/css/themes.css new file mode 100644 index 0000000..64f79b5 --- /dev/null +++ b/new/apps/web/src/php/static/css/themes.css @@ -0,0 +1,80 @@ +:root, :root[data-theme="classic-mode"] { + --color-scheme: dark; + --bg-color: #3b4252; + --fg-color: #e0e2e4; + --secondary-bg: #252b2d; + --secondary-fg: #b5b5b5; + --tertiary-bg: #293134; + --widget-emph: #fff; + --logo-bg: #252b2d; + --button-fg: #ccc; + --header-bg: #181d1f; + --box-shadow: #130b00; + --link-secondary: #f77669; + --select-color: #5e81ac; + --tr-even: #ffffff07; + --border-color: #595959; + --partition-bar-filled: hsl(0, 0%, 20%); + --table-color: #fff; + --modal-color: #424242; + --meta-h4-color: #ffffff66; + + --green: #A3BE8C; + --yellow: rgb(235, 203, 139); + --red: rgb(191, 97, 106); + --amd: rgb(215,27,27); + --intel: rgb(8,110,224); +} + +:root[data-theme="light-mode"] { + --color-scheme: only light; + --bg-color: #ffffff; + --fg-color: #0d111388; + --secondary-bg: #f0f0f0; + --secondary-fg: #444; + --tertiary-bg: #e0e0e0; + --widget-emph: black; + --logo-bg: #252b2d; + --button-fg: #222222; + --header-bg: #eeeeee; + --header-dropdown: #d0d0d0; + --box-shadow: #d6d6d6; + --link-secondary: #f77669; + --select-color: #5e81ac; + --tr-even: #ffffff07; + --border-color: #595959; + --partition-bar-filled: hsl(0, 0%, 20%); + --table-color: var(--secondary-fg); + --modal-color: #ffffff; + --meta-h4-color: #333333; + + --green: green; + --yellow: goldenrod; + --red: #ef4444; + --amd: rgb(215,27,27); + --intel: rgb(8,110,224); +} + +:root[data-theme="light-mode"] .accordion-button::after { + filter: invert(1); +} + +:root[data-theme="light-mode"] .modal-header { + color: var(--widget-emph); +} + +:root[data-theme="k9-mode"] { + --color-scheme: dark; + --bg-color: #181a1b; + --modal-color: #232527; + --fg-color: #ddd9d0; + --secondary-bg: #202325; + --widget-bg: #181d1e; + --widget-fg: #ddd9d0; + --heading-color: #181d1e; + --meta-h4-color: #ffffff; + + --green: #72ff72; + --yellow: #e2b23a; + --red: #f04d4d; +} diff --git a/new/apps/web/src/php/static/js/common.js b/new/apps/web/src/php/static/js/common.js new file mode 100644 index 0000000..5f3e2b8 --- /dev/null +++ b/new/apps/web/src/php/static/js/common.js @@ -0,0 +1,104 @@ +let hwapiLocal = true; + +/** + * This is extracted into its own function because we need to call localhost instead of spec-ify.com if there is a + * hwapi dev server currently running. + * + * The path should not start with a slash. + */ +export async function call_hwapi(path, payload, fallbackCallack = () => {}) { + // https://stackoverflow.com/a/57949518 + const isLocalhost = Boolean( + window.location.hostname === 'localhost' || + // [::1] is the IPv6 localhost address. + window.location.hostname === '[::1]' || + // 127.0.0.0/8 is considered localhost for IPv4. + window.location.hostname.match( + /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ + ) + ); + + let rawResponse; + if (isLocalhost && hwapiLocal) { + console.info("Trying local server for hwapi"); + + try { + if (payload) { + rawResponse = await fetch( + `http://localhost:3000/${path}`, + { + method: "POST", + mode: "cors", + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, + body: JSON.stringify(payload) + }, + ); + } else { + rawResponse = await fetch( + `http://localhost:3000/${path}`, + { + method: "GET", + mode: "cors", + headers: { + 'Accept': 'application/json' + } + }, + ); + } + } catch (e) { + fallbackCallack(); + console.warn("Hwapi dev server not online, falling back to spec-ify.com"); + hwapiLocal = false; + } + } + if (!rawResponse) { + if (payload) { + rawResponse = await fetch( + `https://spec-ify.com/${path}`, + { + method: "POST", + mode: "cors", + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, + body: JSON.stringify(payload) + }, + ); + } else { + rawResponse = await fetch( + `https://spec-ify.com/${path}`, + { + method: "GET", + mode: "cors", + headers: { + 'Accept': 'application/json' + } + }, + ); + } + } + + try { + return await rawResponse.json(); + } catch (e) { + if (rawResponse.status !== 404) // prevent error spam + console.error("Could not parse json from hwapi!"); + + return {}; + } +} + +export function createPcieHexId(id) { + id = id.replace("0x", "").toUpperCase(); + const regex = /^[0-9A-F]{4}$/i; + + if (!regex.test(id)) { + id = "0".repeat(4 - id.length) + id; + } + + return id; +} diff --git a/new/apps/web/src/php/static/js/doom-scroll.js b/new/apps/web/src/php/static/js/doom-scroll.js new file mode 100644 index 0000000..57ac08b --- /dev/null +++ b/new/apps/web/src/php/static/js/doom-scroll.js @@ -0,0 +1,324 @@ +import { call_hwapi, createPcieHexId } from "./common.js"; + +/** + * This function contains extremely hacky hacks. + * (a) To avoid scrolling horizontally to the heading when you click on it + * (making the nav bar not visible), we add a dummy span (.linker) which + * is fixed to the left which actually has the id you want to jump to. + * (b) We add two spaces on h2's to give indents to them. This makes it appear + * nested, but it is terrible. + */ +function createLinks(selector) { + // this exists to avoid duplicates + let headings = {}; + + document.querySelectorAll(selector).forEach(e => { + if (e.offsetParent === null) return; // checks if the element is visible + const kebab = e.innerText.toLowerCase().split(" ").join("-") + .replace(/[^a-zA-Z0-9-_]/g, ''); + let num = 1; + while (Object.hasOwn(headings, `${kebab}-${num}`)) + num++; + const slug = `${kebab}-${num}`; + headings[slug] = e.innerText; + + const linker = document.createElement("span"); + linker.classList.add("linker"); + linker.id = slug; + e.prepend(linker); + + const li = document.createElement("li"); + const link = document.createElement("a"); + // TODO: get rid of this abomination + link.innerHTML = e.tagName === "H2" ? `  ${e.innerText}` : e.innerText; + link.style.width = "100%"; + link.href = `#${slug}`; + li.appendChild(link); + document.querySelector("#nav-list").appendChild(li); + }); +} +// there are just too many network adapters/disks lol +// the .item-header class should be added to dynamic headers (i.e. extensions, disks, network adapters, etc.) +createLinks("h1, h2:not(.item-header)"); + +document.querySelector("#nav-collapse").onclick = () => { + document.querySelector("nav").classList.add("nav-collapsed"); + return false; +} + +document.querySelector("#nav-expand").onclick = () => { + document.querySelector("nav").classList.remove("nav-collapsed"); + return false; +} + +// show the debug log when the konami code is pressed +new Konami(() => { + document.querySelector("#debug-log").style.display = "block"; + createLinks("#debug-log h1"); +}); + +// We don't want DataTables to alert errors +DataTable.ext.errMode = 'none'; +// the event handler below will make DataTables errors log in console +// https://datatables.net/reference/event/dt-error +$("table") +.on('error.dt', function (e, settings, techNote, message) { + console.log('An error has been reported by DataTables: ', message); + }); + +// jQuery is needed just for data tables, avoid using elsewhere +$("#temps-table").DataTable({ + paging: false, + searching: false, + info: false +}); +$("#drivers-table").DataTable({ + paging: false, + searching: false, + info: false +}); +$("#installed-apps-table").DataTable({ + paging: false, + searching: false, + info: false +}); +$("#windows-store-table").DataTable({ + paging: false, + searching: false, + info: false, + fallback: false +}); +$("#services-table").DataTable({ + paging: false, + searching: false, + info: false +}); +$("#tasks-table").DataTable({ + paging: false, + searching: false, + info: false +}); +$("#network-connections-table").DataTable({ + paging: false, + searching: false, + info: false +}); +$("#routes-table").DataTable({ + paging: false, + searching: false, + info: false +}); + +// The processes data table contains functionality that I am too lazy to implement in PHP, so it remains in JavaScript +(async () => { + const json = await (await fetch(`files/${PROFILE_NAME}.json`)).json(); + + try { + let groupProcesses = {}; + json.System.RunningProcesses.forEach((e) => { + const isSystemOrNull = + e.ExePath === "Not Found" || + e.ExePath === "SYSTEM" || + e.ExePath.startsWith(null); + const keys = Object.keys(groupProcesses); + // the path is not valid if isSystemOrNull is true + if (isSystemOrNull) { + if (!keys.includes(e.ProcessName)) + groupProcesses[e.ProcessName] = [e]; + else groupProcesses[e.ProcessName].push(e); + } else { + if (!keys.includes(e.ExePath)) groupProcesses[e.ExePath] = [e]; + else groupProcesses[e.ExePath].push(e); + } + }); + const displayProcesses = Object.values(groupProcesses).flatMap((e) => { + const count = e.length; + const workingSetReal = e + .map((p) => p.WorkingSet) + .reduce((acc, cur) => acc + cur); + const intl = Intl.NumberFormat("en-US"); + const workingSetMegaBytes = ( + workingSetReal / Math.pow(2, 20) + ).toFixed(2); + const workingSetDisplay = intl.format(workingSetMegaBytes); + return { + ProcessName: `${e[0].ProcessName} (${count})`, + ExePath: e[0].ExePath, + Id: e[0].Id, // We can perhaps make this a list later + WorkingSet: workingSetDisplay, + WorkingSetReal: workingSetReal, + }; + }); + + $("#processes-table").DataTable({ + paging: false, + searching: false, + info: false, + data: displayProcesses, + pageLength: 25, + columns: [ + { data: "Id" }, + { data: "ProcessName" }, + { data: "ExePath" }, + { data: "WorkingSet" }, + { data: "WorkingSetReal" }, + ], + columnDefs: [ + { orderData: [4], targets: [3] }, + { + targets: [4], + searchable: false, + visible: false, + }, + ], + }); + } catch (e) { + console.log("Failed making Running Processes DataTable. Is it blank?"); + console.error(e); + } + + // The hwapi request calls currently takes >1s. It doesn't matter that much, but I am doing this in js so the initial + // page load is a little faster. + /** + * @type string + */ + const cpuName = json["Hardware"]["Cpu"]["Name"]; + const statusSpan = document.querySelector("#hwapi-status"); + + const cpuResponse = await call_hwapi(`api/cpus/?name=${encodeURIComponent( + cpuName + )}`, null, () => { + statusSpan.innerHTML = "Could not connect to local hwapi instance, falling back to spec-ify.com"; + }); + + if (!cpuResponse || !cpuResponse.name) { + statusSpan.textContent = "Could not get database results"; + } + + // update the title element to reflect the name fetched from the database + document.querySelector("#hwapi-header").textContent += ` for ${cpuResponse.name}`; + let tableContents = ""; + // add new elements to the table for every kv in the database + for (const [key, value] of Object.entries(cpuResponse.attributes)) { + tableContents += `${key}${value}`; + } + // cpuTable.innerHTML = tableContents; + document.getElementById("hwapi-body").innerHTML = tableContents; + + const deviceTrs = document.querySelectorAll("#devices-table tbody tr"); + + let usbIndexes = []; + let usbValues = []; + let pcieIndexes = []; + let pcieValues = []; + + // go through all the devices and build an array to + deviceTrs.forEach((tr, index) => { + const jsonDevice = json["Hardware"]["Devices"][index]; + if (jsonDevice.DeviceID.startsWith("USB")) { + usbIndexes.push(index); + usbValues.push(jsonDevice["DeviceID"]); + } + if (jsonDevice.DeviceID.startsWith("PCI")) { + pcieIndexes.push(index); + pcieValues.push(jsonDevice["DeviceID"]); + } + }) + + const usbResponsePromise = call_hwapi('api/usbs/', usbValues); + const pcieResponsePromise = call_hwapi('api/pcie/', pcieValues); + const [usbResponse, pcieResponse] = await Promise.all([usbResponsePromise, pcieResponsePromise]); + + deviceTrs.forEach((tr, trIndex) => { + const usbArrayIndex = usbIndexes.indexOf(trIndex); + const pcieArrayIndex = pcieIndexes.indexOf(trIndex); + + if (usbArrayIndex !== -1 && usbResponse[usbArrayIndex]) { // the value is a usb device and it was found + const response = usbResponse[usbArrayIndex]; + const vendor = document.createElement("td"); + vendor.innerText = response.vendor || ""; + tr.appendChild(vendor); + const device = document.createElement("td"); + device.innerText = response.device || ""; + tr.appendChild(device); + const subsystem = document.createElement("td"); // no subsystem for usb + tr.appendChild(subsystem); + } else if (pcieArrayIndex !== -1 && pcieResponse[pcieArrayIndex]) { + const response = pcieResponse[pcieArrayIndex]; + const vendor = document.createElement("td"); + vendor.innerText = response.vendor || ""; + tr.appendChild(vendor); + const device = document.createElement("td"); + device.innerText = response.device || ""; + tr.appendChild(device); + const subsystem = document.createElement("td"); + subsystem.innerText = response.subsystem || ""; + tr.appendChild(subsystem); + } else { + tr.innerHTML += ""; + } + + const linker = document.createElement("span"); + linker.classList.add("linker"); + linker.id = `device-${trIndex}`; + tr.appendChild(linker); + }); + document.querySelector("#devices-sort-warning").style.display = "none"; + $("#devices-table").DataTable({ + paging: false, + searching: false, + info: false, + order: [] // to prevent order changing on data table load + }); + + let bugcheckMalformed = false; + // bugcheck replacemenet for unexpected shutdowns + const bugCheckCodes = json['Events']['UnexpectedShutdowns'].map(shutdown => { + if (!Number.isSafeInteger(shutdown['BugcheckCode'])) bugcheckMalformed = true; + return shutdown['BugcheckCode']; + }); + if (bugcheckMalformed) { // if one of them is not an integer for now, we can add more checks later + console.error("BugCheck codes malformed") + } else { + const response = await call_hwapi(`api/bugcheck/`, bugCheckCodes); + response.forEach((bugcheck, index) => { + //console.table({ index: index, ...bugcheck}); + if (bugcheck && bugcheck.name) { + // this refers to the bugcheckcode column. we need to use "... tbody tr" because otherwise it will select the header row too + const parent = document.querySelectorAll("#unexpected-shutdowns-table tbody tr")[index].querySelectorAll("td")[1]; + parent.innerHTML = ""; // clear code that was inserted in php + const a = document.createElement("a"); // i think inserting it like this is better for sanitation + a.href = bugcheck.url; + a.title = bugcheck.name; // these names can be very long so we're making it a tooltip instead + //a.innerText = `${bugcheck.name} (0x${bugcheck.code.toString(16)})`; + a.innerText = `0x${bugcheck.code.toString(16)}`; + parent.appendChild(a); + } + }); + } + + document.querySelectorAll("#pcie-whea-table tbody tr").forEach((tr, trIndex) => { + const vendorString = `VEN_${createPcieHexId(json['Events']['PciWheaErrors'][trIndex]['VendorId'])}`; + const deviceString = `DEV_${createPcieHexId(json['Events']['PciWheaErrors'][trIndex]['DeviceId'])}`; + for (const [index, device] of json['Hardware']['Devices'].entries()) { + if (device['DeviceID'].includes(vendorString) && device['DeviceID'].includes(deviceString)) { + const matchTd = tr.querySelectorAll("td")[3]; + matchTd.innerText = `${device['Name']} `; + const jumpLink = document.createElement("a"); + jumpLink.innerText = "Jump"; + jumpLink.href = `#device-${index}`; + + jumpLink.onclick = () => { + // can't use jumpLink.href here because that makes it the whole link + document.querySelector(`#device-${index}`).parentElement.classList.add("tr-focus"); + setTimeout(() => { + document.querySelector(`#device-${index}`).parentElement.classList.remove("tr-focus"); + }, 3000); + } + + matchTd.appendChild(jumpLink); + break; + } + } + }) +})(); diff --git a/new/apps/web/src/php/static/js/konami.js b/new/apps/web/src/php/static/js/konami.js new file mode 100644 index 0000000..3617027 --- /dev/null +++ b/new/apps/web/src/php/static/js/konami.js @@ -0,0 +1,186 @@ +/* + * Konami-JS ~ + * :: Now with support for touch events and multiple instances for + * :: those situations that call for multiple easter eggs! + * Code: https://github.com/georgemandis/konami-js + * Copyright (c) 2009 George Mandis (https://george.mand.is) + * Version: 1.6.3 (11/11/2021) + * Licensed under the MIT License (http://opensource.org/licenses/MIT) + * Tested in: Safari 4+, Google Chrome 4+, Firefox 3+, IE7+, Mobile Safari 2.2.1+ and Android + + MIT License + + Copyright (c) 2017 Snaptortoise + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +var Konami = function (callback) { + var konami = { + addEvent: function (obj, type, fn, ref_obj) { + if (obj.addEventListener) obj.addEventListener(type, fn, false); + else if (obj.attachEvent) { + // IE + obj["e" + type + fn] = fn; + obj[type + fn] = function () { + obj["e" + type + fn](window.event, ref_obj); + }; + obj.attachEvent("on" + type, obj[type + fn]); + } + }, + removeEvent: function (obj, eventName, eventCallback) { + if (obj.removeEventListener) { + obj.removeEventListener(eventName, eventCallback); + } else if (obj.attachEvent) { + obj.detachEvent(eventName); + } + }, + input: "", + pattern: "38384040373937396665", + keydownHandler: function (e, ref_obj) { + if (ref_obj) { + konami = ref_obj; + } // IE + konami.input += e ? e.keyCode : event.keyCode; + if (konami.input.length > konami.pattern.length) { + konami.input = konami.input.substr( + konami.input.length - konami.pattern.length + ); + } + if (konami.input === konami.pattern) { + konami.code(konami._currentLink); + konami.input = ""; + e.preventDefault(); + return false; + } + }, + load: function (link) { + this._currentLink = link; + this.addEvent(document, "keydown", this.keydownHandler, this); + this.iphone.load(link); + }, + unload: function () { + this.removeEvent(document, "keydown", this.keydownHandler); + this.iphone.unload(); + }, + code: function (link) { + window.location = link; + }, + iphone: { + start_x: 0, + start_y: 0, + stop_x: 0, + stop_y: 0, + tap: false, + capture: false, + orig_keys: "", + keys: [ + "UP", + "UP", + "DOWN", + "DOWN", + "LEFT", + "RIGHT", + "LEFT", + "RIGHT", + "TAP", + "TAP", + ], + input: [], + code: function (link) { + konami.code(link); + }, + touchmoveHandler: function (e) { + if (e.touches.length === 1 && konami.iphone.capture === true) { + var touch = e.touches[0]; + konami.iphone.stop_x = touch.pageX; + konami.iphone.stop_y = touch.pageY; + konami.iphone.tap = false; + konami.iphone.capture = false; + konami.iphone.check_direction(); + } + }, + touchendHandler: function () { + konami.iphone.input.push(konami.iphone.check_direction()); + + if (konami.iphone.input.length > konami.iphone.keys.length) + konami.iphone.input.shift(); + + if (konami.iphone.input.length === konami.iphone.keys.length) { + var match = true; + for (var i = 0; i < konami.iphone.keys.length; i++) { + if (konami.iphone.input[i] !== konami.iphone.keys[i]) { + match = false; + } + } + if (match) { + konami.iphone.code(konami._currentLink); + } + } + }, + touchstartHandler: function (e) { + konami.iphone.start_x = e.changedTouches[0].pageX; + konami.iphone.start_y = e.changedTouches[0].pageY; + konami.iphone.tap = true; + konami.iphone.capture = true; + }, + load: function (link) { + this.orig_keys = this.keys; + konami.addEvent(document, "touchmove", this.touchmoveHandler); + konami.addEvent( + document, + "touchend", + this.touchendHandler, + false + ); + konami.addEvent(document, "touchstart", this.touchstartHandler); + }, + unload: function () { + konami.removeEvent( + document, + "touchmove", + this.touchmoveHandler + ); + konami.removeEvent(document, "touchend", this.touchendHandler); + konami.removeEvent( + document, + "touchstart", + this.touchstartHandler + ); + }, + check_direction: function () { + x_magnitude = Math.abs(this.start_x - this.stop_x); + y_magnitude = Math.abs(this.start_y - this.stop_y); + x = this.start_x - this.stop_x < 0 ? "RIGHT" : "LEFT"; + y = this.start_y - this.stop_y < 0 ? "DOWN" : "UP"; + result = x_magnitude > y_magnitude ? x : y; + result = this.tap === true ? "TAP" : result; + return result; + }, + }, + }; + + typeof callback === "string" && konami.load(callback); + if (typeof callback === "function") { + konami.code = callback; + konami.load(); + } + + return konami; +}; + +if (typeof module !== "undefined" && typeof module.exports !== "undefined") { + module.exports = Konami; +} else { + if (typeof define === "function" && define.amd) { + define([], function () { + return Konami; + }); + } else { + window.Konami = Konami; + } +} diff --git a/new/apps/web/src/php/static/js/main.js b/new/apps/web/src/php/static/js/main.js new file mode 100755 index 0000000..5052788 --- /dev/null +++ b/new/apps/web/src/php/static/js/main.js @@ -0,0 +1,238 @@ +var devClick = 0; + +// List of all tabs +const tabs = [ + "#pups", + "#notes", + "#variables", + "#browsers", + "#startup", + "#updates", +]; + +for (const tab of tabs) { + if (tab === "#notes"){ + document.querySelector(`${tab}-button`).addEventListener("click", async () => { + showTab(tab); + + if (devClick === 0) {devClickReset = setTimeout(function() { devClick = 0; }, 1000);} + if (++devClick === 3) { + openDevDiv(); + clearTimeout(devClickReset); + } + }); + } + else { + document.querySelector(`${tab}-button`).addEventListener("click", () => { showTab(tab) }); + } +} + +/** + * Toggle the currently displayed tab in the main view + * @param {("#pups" | "#notes" | "#variables" | "#startup" | "#updates")} tab + */ +function showTab(tab) { + // Removes selected tab + const hiddenTabs = tabs.filter((val) => val !== tab); + for (const t of hiddenTabs) { + $(t).hide(); + } + $(tab).show(); +} + +// TODO: the way this is defined is a little bit weird, could probably be improved, it's currently defined by updating the value on the global `window` object +console.log(PROFILE_NAME); + +// Interactivity for the cpu and motherboard widgets +{ + // Interactivity for the show more and hide more buttons for the motherboard widget + document.querySelector("#board-info-more-info-button").addEventListener("click", () => { + document.querySelector("#board-info-more-info").style.display = "block"; + document.querySelector("#board-info-more-info-button").style.display = + "none"; + }); + document.querySelector("#board-info-close").addEventListener("click", () => { + document.querySelector("#board-info-more-info").style.display = "none"; + document.querySelector("#board-info-more-info-button").style.display = + "inline-block"; + }); + + // Interactivity for the show more and hide buttons for the cpu widget + document.querySelector("#cpu-close-button").addEventListener("click", () => { + document.querySelector("#cpu-more-info-button").style.display = ""; + document.querySelector("#cpu-info-table").style.display="none"; + }); + document.querySelector("#cpu-more-info-button").addEventListener("click", () => { + document.querySelector("#cpu-more-info-button").style.display = "none"; + document.querySelector("#cpu-info-table").style.display=""; + }); +} + +// When the selected view is changed (eg, gesp mode or doomscroll), redirect the user to that page +document.querySelector("#view-toggle").addEventListener("change", e => { + const selectedView = e.target.value; + const url = new URL(window.location); + url.searchParams.append("view", selectedView); + window.location = url.toString(); +}); + +// This is extremely jank, but it works! - K9 +// Add functionality to the "Collapse all"/"Expand all" button at the top of the main viewer page +{ + document.getElementById("collapse-toggle").addEventListener("click", () => { + document.getElementById("collapse-toggle").style.display = "none"; + document.getElementById("collapse-toggle-hide").style.display = "inline"; + const accordions = document.getElementsByClassName("accordion-collapse"); + for (const accordion of accordions) { + accordion.classList.add("show"); + } + }); + document.getElementById("collapse-toggle-hide").addEventListener("click", () => { + document.getElementById("collapse-toggle").style.display = "inline"; + document.getElementById("collapse-toggle-hide").style.display = "none"; + const accordions = document.getElementsByClassName("accordion-collapse"); + for (const accordion of accordions) { + accordion.classList.remove("show"); + } + }); +} + +// This could definitely be cleaned up more, for now we hand pick accordion elements to scroll into when expanded +{ + // Where the first item is the id of a button to add an event listener to, and the second item is the id of the element to scroll into + const elementsToScrollInto = [ + ["devices-table-button", "devices"], + ["drivers-table-button", "drivers"], + ["running-processes-button", "running-processes"], + ["installed-app-button", "installed-app"], + ["services-table-button", "services"], + ["tasks-table-button", "tasks"], + ["netcon-table-button", "netcon"], + ["routes-table-button", "routes"], + ]; + for (const [button, elementToScrollInto] of elementsToScrollInto) { + document.getElementById(button).addEventListener("click", () => { + document.getElementById(elementToScrollInto).scrollIntoView({ + behavior: "smooth", + block: "start", + inline: "nearest", + }); + }); + } +} + +document.querySelector("#searchbar-div").onkeyup = searchFunction; + +//Don't even ask. +//Setting the target as the searchbar, sanitizing the inputs into the search bar into lower case, then getting all divs by class of widget into an array and looping +//through them for each keystroke, setting visibility of matched divs with class widget, searching the text into their h1 children. +function searchFunction() { + let txtValue, h1; + const input = document.getElementById("searchbar-div"); + const filter = input.value.toUpperCase(); + const mainBody = document.getElementById("main"); + const widgets = mainBody.getElementsByClassName("widget"); + + for (const widget of widgets) { + if (widget.getElementsByTagName("h1")[0]) { + h1 = widget.getElementsByTagName("h1")[0]; + } + txtValue = h1.textContent || h1.innerText; + if (txtValue.toUpperCase().indexOf(filter) > -1) { + widget.style.display = ""; + } else { + widget.style.display = "none"; + } + } +} + +// Button in the bottom right that scrolls the page back to the top +{ + const topButton = document.getElementById("btn-back-to-top"); + // Show the top button if the page isn't at the top + // and hide it if it is + document.addEventListener("scroll", () => { + if ( + document.body.scrollTop > 20 || + document.documentElement.scrollTop > 20 + ) { + topButton.style.opacity = 1; + topButton.style.visibility = "visible"; + } else { + topButton.style.opacity = 0; + setTimeout(() => { + topButton.style.visibility = "hidden"; + }, "100"); + } + }) + // Scroll the page to the top when clicked + topButton.addEventListener("click", () => { + document.body.scrollTop = 0; + document.documentElement.scrollTop = 0; + }); +} + +function openDevDiv(){ + const devDiv = document.getElementById("dev-div"); + devDiv.style.display = "block"; + devDiv.scrollIntoView(); +} + +// Konami Code - Shows Debug Log +// KonamiJS Code from https://github.com/georgemandis/konami-js +new Konami( + () => (openDevDiv()) +); + +// populate the cpu info table with stuff from hwapi +(async () => { + const report = await (await fetch(`./files/${PROFILE_NAME}.json`)).json(); + /** + * @type string + */ + const cpuName = report["Hardware"]["Cpu"]["Name"]; + + let response; + if (window.location.host.startsWith("localhost")) { + console.info("Trying local server for hwapi"); + try { + response = await ( + await fetch( + `http://localhost:3000/api/cpus/?name=${encodeURIComponent( + cpuName + )}`, + { + method: "GET", + mode: "cors", + } + ) + ).json(); + } catch (e) { + console.warn("Could not connect to local hwapi instance, falling back to spec-ify.com"); + } + } + if (!response) { + response = await ( + await fetch( + `https://spec-ify.com/api/cpus/?name=${encodeURIComponent( + cpuName + )}`, + { + method: "GET", + mode: "cors", + } + ) + ).json(); + } + const titleElement = document.getElementById("cpu-info-title"); + // update the title element to reflect the name fetched from the database + document.getElementById("cpu-info-title").innerHTML = + titleElement.innerHTML.slice(0, -3) + response.name; + let tableContents = ""; + // add new elements to the table for every kv in the database + for (const [key, value] of Object.entries(response.attributes)) { + tableContents += `${key}${value}`; + } + // cpuTable.innerHTML = tableContents; + document.getElementById("fetched-cpu-info").innerHTML = tableContents; +})(); diff --git a/new/apps/web/src/php/static/js/redir.js b/new/apps/web/src/php/static/js/redir.js new file mode 100644 index 0000000..bca5772 --- /dev/null +++ b/new/apps/web/src/php/static/js/redir.js @@ -0,0 +1,6 @@ +let viewmodebutton = document.getElementById("spec-toggle"); +viewmodebutton.addEventListener("click", preserveViewmode); +function preserveViewmode() { + console.log('click'); + window.localStorage.removeItem('viewmode'); +} diff --git a/new/apps/web/src/php/static/js/tables.js b/new/apps/web/src/php/static/js/tables.js new file mode 100644 index 0000000..4701279 --- /dev/null +++ b/new/apps/web/src/php/static/js/tables.js @@ -0,0 +1,817 @@ +import { call_hwapi, createPcieHexId } from "./common.js"; + +const filename = `files/${PROFILE_NAME}.json`; + +async function dataTables() { + + const json = await (await fetch(filename)).json(); + + modalsTables(json); + devicesAndDrivers(json); + appsTables(json); + servicesAndTasks(json); + networkTables(json); + errorTables(json); +} + +function modalsTables(json) { + try { + $("#temp-table").DataTable({ + autoWidth: false, + data: json.Hardware.Temperatures, + columns: [ + { data: "Hardware" }, + { data: "SensorName" }, + { data: "SensorValue" }, + ], + }); + } catch (e) { + console.log("Failed making Temperature DataTable"); + console.log(e.name + ": " + e.message); + } + + try { + $("#power-table").DataTable({ + autoWidth: false, + searching: false, + ordering: false, + paging: false, + data: json.System.PowerProfiles, + columns: [ + { data: "Description" }, + { data: "ElementName" }, + { data: "InstanceID" }, + { data: "IsActive" }, + ], + }); + } catch (e) { + console.log("Failed making Power Profile DataTable"); + console.log(e.name + ": " + e.message); + } + + //This function broke me as a human being. + //We do a single entrypoint ajax call to the json file like all other table generations, except we have a situation where we have an unknown amount of browsers, each with + //an unknown amount of profiles, each with an unknown amount of extensions installed. + //One part of this is done in lines 1128~ and onwards(as of commit when writing this comment). PHP creates a table element for each of the browser profiles + //then the code below will follow the same naming convention to linearly populate each appropriate table with it's data. + //At first I experimented with creating the divs and table dynamically with JS, but datatable would not initialize on a newly created div no matter what I did. + //This works, and it seems to work great too. But who knows. + try { + var Browsers = Object.keys(json.System.BrowserExtensions); + Browsers.forEach(function (Browser) { + var Profiles = Object.keys( + json.System.BrowserExtensions[Browser].Profiles + ); + Profiles.forEach(function (Profile) { + let BrowserName = + "#" + + json.System.BrowserExtensions[Browser].Name + + "Profile" + + [Profile] + + "Table"; + let BrowserJsonData = + json.System.BrowserExtensions[Browser].Profiles[Profile] + .Extensions; + BrowserJsonData = BrowserJsonData.filter((e) => e != null); + $(BrowserName).DataTable({ + autoWidth: false, + searching: false, + ordering: false, + paging: false, + data: BrowserJsonData, + columns: [ + { data: "name" }, + { data: "version" }, + { data: "description" }, + ], + }); + }); + }); + } catch (e) { + console.log("Failed making Browser Extension DataTable"); + console.log(e.name + ": " + e.message); + } + + try { + $("#audio-table").DataTable({ + autoWidth: false, + searching: false, + ordering: false, + paging: false, + data: json.Hardware.AudioDevices, + columns: [ + { data: "DeviceID" }, + { data: "Manufacturer" }, + { data: "Name" }, + { data: "Status" }, + ], + }); + } catch (e) { + console.log("Failed making Audio Devices DataTable"); + console.log(e.name + ": " + e.message); + } + + try { + $("#battery-table").DataTable({ + autoWidth: false, + data: json.Hardware.Batteries, + searching: false, + ordering: false, + paging: false, + columns: [ + { data: "Name" }, + { data: "Manufacturer" }, + { data: "Chemistry" }, + { data: "Design_Capacity" }, + { data: "Full_Charge_Capacity" }, + ], + }); + } catch (e) { + console.log("Failed making Audio Devices DataTable"); + console.log(e.name + ": " + e.message); + } +} + +function devicesAndDrivers(json){ + try { + json.Hardware.Devices.map(row => { + if (row.Status === "Error") { + row.Status = `Error (${row.ConfigManagerErrorCode})`; + } + + return row; + }); + + $("#devices-table").DataTable({ + autoWidth: false, + data: json.Hardware.Devices, + columns: [ + { + data: "Status" + }, + { data: "Description" }, + { data: "Name" }, + { data: "DeviceID" }, + ], + }); + } catch (e) { + console.log("Failed making Devices DataTable"); + console.log(e.name + ": " + e.message); + } + + try { + $("#drivers-table").DataTable({ + autoWidth: false, + data: json.Hardware.Drivers, + columns: [ + { data: "DeviceName" }, + { data: "FriendlyName" }, + { data: "Manufacturer" }, + { data: "DeviceID" }, + { data: "DriverVersion" }, + ], + }); + } catch (e) { + console.log("Failed making Drivers DataTable"); + console.log(e.name + ": " + e.message); + } +} + +function appsTables(json) { + try { + let groupProcesses = {}; + json.System.RunningProcesses.forEach((e) => { + const isSystemOrNull = + e.ExePath === "Not Found" || + e.ExePath === "SYSTEM" || + e.ExePath.startsWith(null); + const keys = Object.keys(groupProcesses); + // the path is not valid if isSystemOrNull is true + if (isSystemOrNull) { + if (!keys.includes(e.ProcessName)) + groupProcesses[e.ProcessName] = [e]; + else groupProcesses[e.ProcessName].push(e); + } else { + if (!keys.includes(e.ExePath)) groupProcesses[e.ExePath] = [e]; + else groupProcesses[e.ExePath].push(e); + } + }); + const displayProcesses = Object.values(groupProcesses).flatMap((e) => { + const count = e.length; + const workingSetReal = e + .map((p) => p.WorkingSet) + .reduce((acc, cur) => acc + cur); + const intl = Intl.NumberFormat("en-US"); + const workingSetMegaBytes = ( + workingSetReal / Math.pow(2, 20) + ).toFixed(2); + const workingSetDisplay = intl.format(workingSetMegaBytes); + return { + ProcessName: `${e[0].ProcessName} (${count})`, + ExePath: e[0].ExePath, + Id: e[0].Id, // We can perhaps make this a list later + WorkingSet: workingSetDisplay, + WorkingSetReal: workingSetReal, + }; + }); + + $("#running-processes-table").DataTable({ + autoWidth: false, + data: displayProcesses, + pageLength: 25, + columns: [ + { data: "Id" }, + { data: "ProcessName" }, + { data: "ExePath" }, + { data: "WorkingSet" }, + { data: "WorkingSetReal" }, + ], + columnDefs: [ + { orderData: [4], targets: [3] }, + { + targets: [4], + searchable: false, + visible: false, + }, + ], + }); + } catch (e) { + console.log("Failed making Running Processes DataTable. Is it blank?"); + console.log(e.name + ": " + e.message); + } + + try { + $("#installed-app-table").DataTable({ + autoWidth: false, + data: json.System.InstalledApps, + columns: [ + { data: "Name" }, + { data: "Version" }, + { data: "InstallDate" }, + ], + }); + } catch (e) { + console.log("Failed making Installed Apps DataTable"); + console.log(e.name + ": " + e.message); + } + + if (document.getElementById("installed-windows-store-table")){ + try { + $("#installed-windows-store-table").DataTable({ + autoWidth: false, + pageLength: 25, + data: json.System.WindowsStorePackages, + columns: [ + { data: "Name" }, + { data: "ProgramId" }, + { data: "Vendor" }, + { data: "Version" }, + ], + }); + } catch (e){ + console.log("Failed making Windows Store Packages table"); + console.log(e.name + ": " + e.message); + } + } +} + +function servicesAndTasks(json) { + try { + $("#services-table").DataTable({ + autoWidth: false, + data: json.System.Services, + pageLength: 25, + columns: [ + { data: "State" }, + { data: "Caption" }, + { data: "Name" }, + { data: "PathName" }, + { data: "StartMode" }, + ], + }); + } catch (e) { + console.log("Failed making Services DataTable"); + console.log(e.name + ": " + e.message); + } + + try { + $("#tasks-table").DataTable({ + autoWidth: false, + data: json.System.ScheduledTasks, + pageLength: 25, + columns: [ + { data: "State" }, + { data: "IsActive" }, + { data: "Name" }, + { data: "Path" }, + { data: "Author" }, + { data: "TriggerTypes" }, + ], + }); + } catch (e) { + console.log("Failed making Tasks DataTable"); + console.log(e.name + ": " + e.message); + } +} + +function networkTables(json) { + try { + $("#netcon-table").DataTable({ + autoWidth: false, + data: json.Network.NetworkConnections, + columns: [ + { data: "LocalIPAddress" }, + { data: "LocalPort" }, + { data: "RemoteIPAddress" }, + { data: "RemotePort" }, + { + data: "OwningPID", + render: function (data) { + json.System.RunningProcesses.forEach(function (PID) { + if (PID.Id == data) { + data = PID.ProcessName; + } + }); + return data; + }, + }, + ], + }); + } catch (e) { + console.log("Failed making Network Connections DataTable"); + console.log(e.name + ": " + e.message); + } + + // Clever little trickery in this function actually where I practically use DataTables render functionality to + // InnerJoin the InterfaceIndex from one tree in the json to another tree in the json, thus giving me the ability + // to print out the corresponding name of the NIC that's using a route, instead of just a number. + try { + $("#routes-table").DataTable({ + autoWidth: false, + data: json.Network.Routes, + columns: [ + { data: "Description" }, + { data: "Destination" }, + { + data: "InterfaceIndex" + }, + { data: "Mask" }, + { data: "Metric1" }, + { data: "NextHop" }, + ], + }); + } catch (e) { + console.log("Failed making Routes DataTable"); + console.log(e.name + ": " + e.message); + } +} + +async function errorTables(json) { + // Unexpected Shutdowns + try { + function format(d) { + return ( + `
Bugcheck Parameter 1: ${d.BugcheckParameter1}
` + + `
Bugcheck Parameter 2: ${d.BugcheckParameter2}
` + + `
Bugcheck Parameter 3: ${d.BugcheckParameter3}
` + + `
Bugcheck Parameter 4: ${d.BugcheckParameter4}
` + ); + } + + let bugcheckMalformed = false; + // bugcheck replacemenet for unexpected shutdowns + const bugCheckCodes = json['Events']['UnexpectedShutdowns'].map(shutdown => { + if (!Number.isSafeInteger(shutdown['BugcheckCode'])) bugcheckMalformed = true; + return shutdown['BugcheckCode']; + }); + let bugCheckTable = {} + if (bugcheckMalformed) { // if one of them is not an integer for now, we can add more checks later + throw new Error("BugCheck codes malformed"); + } else { + const response = await call_hwapi(`api/bugcheck/`, bugCheckCodes); + response.forEach((bugcheck, index) => { + //console.table({ index: index, ...bugcheck}); + if (bugcheck && bugcheck.name) { + const a = document.createElement("a"); // i think inserting it like this is better for sanitation + a.href = bugcheck.url; + a.title = bugcheck.name; // these names can be very long so we're making it a tooltip instead + //a.innerText = `${bugcheck.name} (0x${bugcheck.code.toString(16)})`; + a.innerText = `0x${bugcheck.code.toString(16)}`; + bugCheckTable[bugcheck.code] = a.outerHTML; + } + }); + } + + let unexpectedShutdownsTable = new DataTable(("#unexpected-shutdowns-table"), { + autoWidth: false, + data: json.Events.UnexpectedShutdowns, + columns: [ + { + className: 'dt-control', + orderable: false, + data: null, + defaultContent: '', + width: '2%', + }, + { data: "Timestamp" }, + { data: "PowerButtonTimestamp" }, + { data: "BugcheckCode", + render: function (data) { + return bugCheckTable[data] ?? `0x${data.toString(16)}`; + } + }, + ], + order: [[1,"desc"]], + }); + + unexpectedShutdownsTable.on('click', 'td', function (e) { + let tr = e.target.closest('tr'); + let row = unexpectedShutdownsTable.row(tr); + + if (row.child.isShown()) { + // This row is already open - close it + row.child.hide(); + } + else { + // Open this row + row.child(format(row.data())).show(); + } + }); + } catch (e) { + console.log("Failed making Unexpected Shutdowns DataTable"); + console.log(e.name + ": " + e.message); + } + + // Machine Check Exception Table + try { + function format(d) { + return ( + ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Timestamp${d.Timestamp}
MCI Status Register Valid${d.MciStatusRegisterValid}
Error Overflow${d.ErrorOverflow}
Uncorrected Error${d.UncorrectedError}
Error Reporting Enabled${d.ErrorReportingEnabled}
Processor Context Corrupted${d.ProcessorContextCorrupted}
Poisoned Data${d.PoisonedData}
Extended Error Code${d.ExtendedErrorCode}
MCA Error Code${d.McaErrorCode}
Error Message${d.ErrorMessage}
Transaction Type${d.TransactionType}
Memory Heirarchy Level${d.MemoryHeirarchyLevel}
Request Type${d.RequestType}
Participation${d.Participation}
Timeout${d.Timeout}
Memory Or I/O${d.MemoryOrIo}
Memory Transaction Type${d.MemoryTransactionType}
Channel Number${d.ChannelNumber}
+ ` + ); + } + + let mceTable = new DataTable("#mce-table", { + autoWidth: false, + data: json.Events.MachineCheckExceptions, + columns: [ + { + className: 'dt-control', + orderable: false, + data: null, + defaultContent: '', + width: '2%', + }, + { data: "Timestamp" }, + { data: "McaErrorCode" }, + { data: "ErrorMessage" }, + { data: "TransactionType" }, + ], + order: [[1,"desc"]], + }); + + mceTable.on('click', 'td.dt-control', function (e) { + let tr = e.target.closest('tr'); + let row = mceTable.row(tr); + + if (row.child.isShown()) { + // This row is already open - close it + row.child.hide(); + } + else { + // Open this row + row.child(format(row.data())).show(); + } + }); + } catch (e) { + console.log("Failed making Machine Check Exception DataTable"); + console.log(e.name + ": " + e.message); + } + + // WHEA Error Records Error + try { + function format(d) { + + let errorDescriptors = `
+ Error Descriptors`; + + d.ErrorDescriptors.forEach((item) => { + errorDescriptors += ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Section Offset${item.SectionOffset}
Section Length${item.SectionLength}
Revision${item.Revision}
Valid Bits${item.ValidBits}
Flags${item.Flags}
Section Type${item.SectionType}
FRU ID${item.FRUId}
Section Severity${item.SectionSeverity}
FRU Text${item.FRUText}
` + }); + + errorDescriptors += `
`; + + return ( + // Error Header + ` +
+ Error Header + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Signature${d.ErrorHeader.Signature}
Revision${d.ErrorHeader.Revision}
Signature End${d.ErrorHeader.SignatureEnd}
Section Count${d.ErrorHeader.SectionCount}
Severity${d.ErrorHeader.Severity}
Valid Bits${d.ErrorHeader.ValidBits}
Length${d.ErrorHeader.Length}
Timestamp${d.ErrorHeader.Timestamp}
Platform ID${d.ErrorHeader.PlatformId}
Partition ID${d.ErrorHeader.PartitionId}
Creator ID${d.ErrorHeader.CreatorId}
Notify Type${d.ErrorHeader.NotifyType}
Record ID${d.ErrorHeader.RecordId}
Flags${d.ErrorHeader.Flags}
Persistence Info${d.ErrorHeader.PersistenceInfo}
+
+ ` + + + // Error Descriptors + errorDescriptors + + + // Error Packets + ` +
+ Error Packets +
${d.ErrorPackets}
+
+ ` + ); + } + + let wheaErrorRecordsTable = new DataTable("#whea-records-table", { + autoWidth: false, + data: json.Events.WheaErrorRecords, + columns: [ + { + className: 'dt-control', + orderable: false, + data: null, + defaultContent: '', + width: '2%', + }, + { data: "ErrorHeader.Severity" }, + { data: "ErrorHeader.Timestamp" }, + { data: "ErrorHeader.PlatformId" }, + { data: "ErrorHeader.CreatorId" }, + { data: "ErrorHeader.NotifyType" }, + ], + }); + + wheaErrorRecordsTable.on('click', 'td.dt-control', function (e) { + let tr = e.target.closest('tr'); + let row = wheaErrorRecordsTable.row(tr); + + if (row.child.isShown()) { + // This row is already open - close it + row.child.hide(); + } + else { + // Open this row + row.child(format(row.data())).show(); + } + }); + } catch (e) { + console.log("Failed making WHEA Error Records DataTable"); + console.log(e.name + ": " + e.message); + } + + // PCI WHEA Error + try { + // this might be the most scuffed code that i have ever written + // this works similarly to how doom-scroll.js does it, + // so it runs through all of the items and pushes it to a + // separate array. but then it pushes it back to the inner rep + // of the data. very stupid but it works so im not gonna + // change it. i need coffee - k9 + + let inputIds = []; + + json.Events.PciWheaErrors.forEach((data) => { + inputIds.push(`PCI\\VEN_${createPcieHexId(data.VendorId)}&DEV_${createPcieHexId(data.DeviceId)}`); + }); + + let responseIds = await call_hwapi('api/pcie/', inputIds); + + json.Events.PciWheaErrors.forEach((data, index) => { + json["Events"]["PciWheaErrors"][index]["Vendor"] = responseIds[index]["vendor"] + json["Events"]["PciWheaErrors"][index]["Subsystem"] = responseIds[index]["subsystem"] + + let vendorIdItem = data.VendorId.replace("0x", "").toUpperCase(); + let deviceIdItem = data.VendorId.replace("0x", "").toUpperCase(); + + json.Hardware.Devices.forEach((deviceData) => { + if (deviceData.DeviceID.includes(vendorIdItem) && deviceData.DeviceID.includes(deviceIdItem)) { + json["Events"]["PciWheaErrors"][index]["Device"] = deviceData.Name; + return; + } + }) + + if (json["Events"]["PciWheaErrors"][index]["Device"] == null){ + json["Events"]["PciWheaErrors"][index]["Device"] = responseIds[index]["vendor"] + } + }); + + new DataTable("#pci-whea-table", { + autoWidth: false, + data: json.Events.PciWheaErrors, + columns: [ + { data: "Timestamp" }, + { data: "VendorId" }, + { data: "DeviceId" }, + { data: "Vendor" }, + { data: "Device" }, + { data: "Subsystem" }, + ], + }); + } catch (e) { + console.log("Failed making PCI WHEA Errors DataTable"); + console.log(e.name + ": " + e.message); + } +} + +dataTables(); + +async function errorcheck() { + const json = await (await fetch(filename)).json(); + let errors = 0; + for (let key in json) { + key = json[key]; + try { + if ("ErrorCount" in key && key["ErrorCount"] > 0) { + for (let elem of document.getElementsByClassName("btn-info")) { + elem.style.backgroundColor = "#d35400"; + elem.style.boxShadow = "0 4px 9px -4px #d35400"; + } + errors += key["ErrorCount"]; + } + } catch { + continue; + } + } + if (errors > 0) {console.log("JSON Errors Total: " + errors);} +} + +errorcheck(); diff --git a/new/apps/web/src/php/static/js/themes.js b/new/apps/web/src/php/static/js/themes.js new file mode 100644 index 0000000..b336c57 --- /dev/null +++ b/new/apps/web/src/php/static/js/themes.js @@ -0,0 +1,21 @@ +//Themes. Could be handled in a better, more efficient way but it does it's job. +// IMPORTANT: the variables are intialized and set to *something* before running the script +let themeBody = null; +let themeTextBox = null; + +const localStorageTheme = window.localStorage.getItem("theme"); +if (localStorageTheme !== null) { + document.querySelector(`#mode-toggle option[value="${localStorageTheme}"]`).setAttribute("selected", ""); + change_theme(); +} + +// Call the function every time it changes +document.querySelector('#mode-toggle').onchange = change_theme; + +function change_theme(){ + // Get selection for the switch + let theme = document.querySelector('#mode-toggle').value; + + document.documentElement.setAttribute("data-theme", theme); + localStorage.setItem("theme", theme); +} diff --git a/new/apps/web/src/php/static/js/upload.js b/new/apps/web/src/php/static/js/upload.js new file mode 100755 index 0000000..eceaed6 --- /dev/null +++ b/new/apps/web/src/php/static/js/upload.js @@ -0,0 +1,56 @@ +//This is the drag and drop upload handler, I wish it was easier, but it's pretty self-explanatory. +let form = document.querySelector("#upload-form"); +let html = document.querySelector("html"); +let text = document.querySelector("#drag-text"); +let box = document.querySelector("#upload-box"); +let input = document.querySelector("#input-file-now"); + +// Prevent Redirect +html.addEventListener("dragover", (e) => { + e.preventDefault(); + e.stopPropagation(); + text.textContent = "Drop it!"; +}); + +html.addEventListener("dragleave", (e) => { + e.preventDefault(); + e.stopPropagation(); +}); + +html.addEventListener("drop", (e) => { + e.preventDefault(); + e.stopPropagation(); +}); + +form.addEventListener("dragenter", (e) => { + e.stopPropagation(); + e.preventDefault(); + box.classList.add("hoverBox"); + text.textContent = "Drop it!"; +}); + +form.addEventListener("dragover", (e) => { + e.stopPropagation(); + e.preventDefault(); + box.classList.add("hoverBox"); + text.textContent = "Drop it!"; +}); + +form.addEventListener("dragleave", (e) => { + box.classList.remove("hoverBox"); + text.textContent = "You tease"; + e.stopPropagation(); + e.preventDefault(); +}); + +// Drop +// Selects the input box, sets the files, and submits it +form.addEventListener("drop", (e) => { + text.textContent = "Thanks! :D"; + input.files = e.dataTransfer.files; + form.submit(); +}); + +input.addEventListener("change", () => { + form.submit(); +}); diff --git a/new/apps/web/src/php/tabbed_info.php b/new/apps/web/src/php/tabbed_info.php new file mode 100644 index 0000000..781070e --- /dev/null +++ b/new/apps/web/src/php/tabbed_info.php @@ -0,0 +1,456 @@ + +
+
+ + + + + + +
+ +
+ + +

General Notes

+ + + +

The OS is + + $oscheck"; ?> + (version , build ) +

+ +

The current uptime is + . +

+ + No AVs found!

'; + } elseif (sizeof($json_data['Security']['AvList']) == 1) { + $av = $json_data["Security"]["AvList"][0]; + echo "

The currently installed AV is {$av}

"; + } else { + $avs = implode(',', array_map(function ($i) { + return ' ' . $i; + }, $json_data['Security']['AvList'])); + echo "

The currently installed AVs are {$avs}

"; + } + + $noteshtml = ''; + + if ($json_data['System']['UsernameSpecialCharacters'] == true) { + $noteshtml .= ' +

+ Username found with Special Characters +

+ '; + } + if ($json_data['System']['OneDriveCommercialPathLength'] != null) { + $noteshtml .= ' +

+ OneDrive Path Length : ' . $json_data['System']['OneDriveCommercialPathLength'] . ' + OneDrive Name Length : ' . $json_data['System']['OneDriveCommercialNameLength'] . ' +

+ '; + } + + if ($json_data['System']['RecentMinidumps'] != 0) { + $noteshtml .= ' +

+ There have been ' . $json_data['System']['RecentMinidumps'] . ' Minidumps found +

+ '; + } + + $hostFileHash = $json_data['Network']['HostsFileHash']; + $hostFileCheck = "2D6BDFB341BE3A6234B24742377F93AA7C7CFB0D9FD64EFA9282C87852E57085" !== $hostFileHash; // Pre-calculated Hash + + if ($hostFileCheck) { + $noteshtml .= ' +

+ Hosts file has been modified from stock +

+ '; + } + + if (!empty($json_data['Hardware']['Batteries'])) { + foreach ($json_data['Hardware']['Batteries'] as $battery) { + $cap = floatval($battery["Remaining_Life_Percentage"]); + if ( + $cap < 70 + ) { + $designcap = $battery['Design_Capacity'] / 1000; + $currentcap = $battery['Full_Charge_Capacity'] / 1000; + $noteshtml .= " +

+ Battery {$battery['Name']} has a diminished capacity (Designed for {$designcap} Wh, currently {$currentcap} Wh) +

"; + } + } + } + + foreach ($json_data['Hardware']['Storage'] as $disk) { + foreach ($disk['Partitions'] as $partNum => $part) { + if (isset($part['DirtyBitSet']) && $part['DirtyBitSet']) { + if (empty($part['PartitionLetter'])) { + $noteshtml .= " +

+ Dirty bit set on partition $partNum ({$disk['DeviceName']}) +

+ "; + } else { + $noteshtml .= " +

+ Dirty bit set on {$part['PartitionLetter']} ({$disk['DeviceName']}) +

+ "; + } + } + } + } + + $unexpected_shutdown_count = $json_data['Events']['UnexpectedShutdownCount']; + $machinecheck_count = $json_data['Events']['MachineCheckExceptionCount']; + $whea_count = $json_data['Events']['WheaErrorRecordCount']; + $pci_whea_count = $json_data['Events']['PciWheaErrorCount']; + if ($unexpected_shutdown_count > 0) { + $noteshtml .= " +

+ $unexpected_shutdown_count Unexpected Shutdowns detected +

+ "; + } + if ($machinecheck_count > 0) { + $noteshtml .= " +

+ $machinecheck_count MachineCheck Exceptions detected +

+ "; + } + if ($whea_count > 0) { + $noteshtml .= " +

+ $whea_count WHEA errors detected +

+ "; + } + if ($pci_whea_count > 0) { + $noteshtml .= " +

+ $pci_whea_count PCI WHEA errors detected +

+ "; + } + + if ($json_data['Meta']['ElapsedTime'] > 20000) { + $noteshtml .= ' +

Specify runtime is over 20s

+ '; + } + + if ($json_data['System']['LimitedMemory']) { + $noteshtml .= ' +

+ Device configured to use a limited amount of memory +

+ '; + } + + if ($json_data['System']['WindowsOld']) { + $noteshtml .= ' +

+ Windows.OLD detected +

+ '; + } + + + + if (!empty($noteshtml)) { + $noteshtml = '
' . $noteshtml; + echo $noteshtml; + } + ?> + + ' + . $storage_device['DeviceName'] . ' (' . $lettersString . ') has ' + . $smartPoint['RawValue'] . ' ' . $smartPoint['Name'] . '

'; + } + } + } + } + + if (abs((floor(bytesToGigabytes($storage_device['DiskCapacity'])) - + floor(bytesToGigabytes(getDriveCapacity($storage_device))))) > 5) { + $drivehtml .= ' +

+ ' . $storage_device['DeviceName'] . ' (' . $lettersString . ') has differing capacities. + (' . floor(bytesToGigabytes($storage_device['DiskCapacity'])) . " on disk vs. " + . floor(bytesToGigabytes(getDriveCapacity($storage_device))) . ' on partitions) +

+ '; + } + $driveKey += 1; + } + + if (!empty($drivehtml)) { + $drivehtml = '

Drive / SMART Notes

' . $drivehtml; + echo $drivehtml; + } + + ?> + + + Static Core Count found set. +

'; + } + + foreach ($json_data['System']['ChoiceRegistryValues'] as $regkey) { + + if ($regkey['Value'] && !in_array($regkey['Value'], $defaultRegKeys[$regkey['Name']])){ + $reghtml .= ' +

+ Registry Value ' . $regkey['Name'] . ' found set, value of ' . $regkey['Value'] . ' +

'; + } + + } + + if (!empty($reghtml)) { + $reghtml = '

Notable Registry Changes

' . $reghtml; + echo $reghtml; + } + ?> + +
+
+ Notable Software found Installed'; + + $puphtml .= ''; + + foreach ($pupsfoundInstalled as $pup) { + $puphtml .= ''; + } + + $puphtml .= '
' . $pup . ' Found installed
'; + } + + if (!empty($pupsfoundRunning)) { + + $puphtml .= '

Notable Software found Running

'; + + $puphtml .= ''; + + foreach ($pupsfoundRunning as $pup) { + $puphtml .= ''; + } + + $puphtml .= '
' . $pup . ' Found Running
'; + } + + if (!empty($puphtml)) { + echo $puphtml; + } else { + echo '

No Notable Software found, yay!

'; + } + ?> +
+
+ + + + + + + User Variables'; + $uservar_keys = array_keys($json_data['System']['UserVariables']); + foreach ($uservar_keys as $uservar) { + if ($uservar != "Path") { + echo ''; + }; + }; + echo '
FieldValue
' . $uservar . '' . $json_data['System']['UserVariables'][$uservar] . '
'; + foreach ($path_array as $path) { + // Only print the path if it starts with a Windows-accepted drive letter + if (preg_match('/^[C-Z]:/', $path)) { + echo ''; + } + } + ?> + +
Path Variables
' . $path . '
+ + + + + + + System Variables'; + $uservar_keys = array_keys($json_data['System']['SystemVariables']); + foreach ($uservar_keys as $uservar) { + if ($uservar != "Path") { + echo ''; + }; + } ?> + +
FieldValue
' . $uservar . '' . $json_data['System']['SystemVariables'][$uservar] . '
+
+
+
+ + +
+
+

' . $browser['Name'] . $default_browser . '

+ +
+
+
+ '; + echo ''; + } + } + ?> +
+
+
+ + + + + + + + + ' . + '' . + '' . + ''; + } + ?> + +
App NameApp PathTimestamp
' . $task['AppName'] . '' . $task['ImagePath'] . '' . $task['Timestamp'] . '
+
+
+ + + + + + + ' . + '' . + ''; + } + ?> +
UpdateInstall Date
' . $update['HotFixID'] . '' . $update['InstalledOn'] . '
+
+ + +
\ No newline at end of file diff --git a/new/apps/web/src/php/tables.php b/new/apps/web/src/php/tables.php new file mode 100644 index 0000000..036ddfc --- /dev/null +++ b/new/apps/web/src/php/tables.php @@ -0,0 +1,310 @@ + +
+
+

+ +

+ +

+ +

+ +
+
+
+
+
+
+

+ +

+ +

+ +

+ + + + + '; + } + ?> + +
+
+
+
+
+
+

+ +

+ +

+ +

+ + +
+
+
+ + +

+ +

+
+ + + + + + + +
TimestampPower Button TimestampBugcheck Code
+
+ '; +} + +if (isset($json_data['Events']['MachineCheckExceptions']) && !($json_data['Events']['MachineCheckExceptions'] === [])) { + $error_div_contents .= '
+

+ +

+
+ + + + + + + + +
TimestampMCA Error CodeError MessageTransaction Type
+
+
'; +} + +if (isset($json_data['Events']['WheaErrorRecords']) && !($json_data['Events']['WheaErrorRecords'] === [])) { + + $error_div_contents .= '
+

+ +

+
+ + + + + + + + + +
SeverityTimestampPlatform IDCreator IDNotify Type
+
+
'; +} + +if (isset($json_data['Events']['PciWheaErrors']) && !($json_data['Events']['PciWheaErrors'] === [])) { + + $error_div_contents .= '
+

+ +

+
+ + + + + + + + + +
TimestampVendorIdDeviceIdVendorDeviceSubsystem
+
+
'; +} + +if (!($error_div_contents === '')) { + $error_div_contents = '
' . $error_div_contents . '
'; + echo $error_div_contents; +} +?> + +
+ +
+ + +
+ \ No newline at end of file diff --git a/new/apps/web/src/php/upload.php b/new/apps/web/src/php/upload.php new file mode 100755 index 0000000..be944ef --- /dev/null +++ b/new/apps/web/src/php/upload.php @@ -0,0 +1,42 @@ +params['name'] ?? 'unknownn'); + return [ + 'message' => "Hello " . $name, + ]; +} +``` + +## Installation + +See https://github.com/basuke/vite-plugin-sveltekit-php-backend + +## License + +MIT diff --git a/new/apps/web/src/php/vendor/basuke/sveltekit-php-backend/composer.json b/new/apps/web/src/php/vendor/basuke/sveltekit-php-backend/composer.json new file mode 100644 index 0000000..37fc8df --- /dev/null +++ b/new/apps/web/src/php/vendor/basuke/sveltekit-php-backend/composer.json @@ -0,0 +1,30 @@ +{ + "name": "basuke/sveltekit-php-backend", + "description": "Supplemental package to support SvelteKit PHP Backend Vite Plugin", + "type": "library", + "license": "MIT", + "keywords": [ + "Svelte", + "SvelteKit", + "Vite", + "Backend" + ], + "homepage": "https://github.com/basuke/sveltekit-php-backend", + "autoload": { + "psr-4": { + "Basuke\\SvelteKit\\": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "authors": [ + { + "name": "Basuke Suzuki", + "email": "basuke@mac.com" + } + ], + "require": { + "php": ">=8.0.0" + } +} diff --git a/new/apps/web/src/php/vendor/basuke/sveltekit-php-backend/src/Backend.php b/new/apps/web/src/php/vendor/basuke/sveltekit-php-backend/src/Backend.php new file mode 100644 index 0000000..04e30a8 --- /dev/null +++ b/new/apps/web/src/php/vendor/basuke/sveltekit-php-backend/src/Backend.php @@ -0,0 +1,76 @@ +run(); + } + } + + private string $namespace; + private Environment $environment; + + public function __construct(string $namespace) { + $this->namespace = $namespace; + $this->environment = new Environment(); + } + + public function run() { + if (!empty($_SERVER['SVELTEKIT_METHOD'])) { + $this->endpoint($_SERVER['SVELTEKIT_METHOD']); + } else if ($_SERVER['REQUEST_METHOD'] === 'GET') { + $this->load(); + } else if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $this->action(); + } else if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { + $this->options(); + } else { + fail(500, ['error' => "Invalid calling convention"]); + } + } + + public function load() { + $method = 'load'; + if (is_callable($method)) { + $event = PageServerEvent::get(); + $result = call_user_func($method, $event); + + json($result); + } else { + fail(500, ['error' => "Function '{$method}' is not defiened or callable"]); + } + } + + public function endpoint(string $method) { + if (is_callable($method)) { + $event = PageServerEvent::get(); + call_user_func($method, $event); + } else { + fail(500, ['error' => "Function '{$method}' is not defiened or callable"]); + } + } + + public function action() { + $action = $_SERVER['SVELTEKIT_ACTION'] ?? 'default'; + global $actions; + if (isset($actions[$action])) { + if (is_callable($actions[$action])) { + $event = PageServerEvent::get(); + call_user_func($actions[$action], $event); + } else { + fail(500, ['error' => "Action '{$action}' is defiened but not callable"]); + } + } else { + fail(500, ['error' => "Action '{$action}' is not defiened"]); + } + } + + public function options() { + json($this->environment); + } +} diff --git a/new/apps/web/src/php/vendor/basuke/sveltekit-php-backend/src/Environment.php b/new/apps/web/src/php/vendor/basuke/sveltekit-php-backend/src/Environment.php new file mode 100644 index 0000000..ede0078 --- /dev/null +++ b/new/apps/web/src/php/vendor/basuke/sveltekit-php-backend/src/Environment.php @@ -0,0 +1,49 @@ +load = self::functionInfo('load'); + + foreach (self::Methods as $method) { + $def = self::functionInfo($method); + if ($def) { + $this->endpoints[$method] = $def; + } + } + + global $actions; + if (is_array($actions)) { + foreach ($actions as $action => $callable) { + $def = self::functionInfo($callable); + if ($def) { + $this->actions[$action] = $def; + } + } + } + } + + public static function functionInfo($callable): ?array { + try { + $function = new \ReflectionFunction($callable); + return array_map(function ($param) { + return self::parameterInfo($param); + }, $function->getParameters()); + } catch (\ReflectionException $e) { + return null; + } + } + + public static function parameterInfo(\ReflectionParameter $param): array { + $name = $param->getName(); + $type = strval($param->getType()); + return [$type, $name]; + } +} diff --git a/new/apps/web/src/php/vendor/basuke/sveltekit-php-backend/src/PageServerEvent.php b/new/apps/web/src/php/vendor/basuke/sveltekit-php-backend/src/PageServerEvent.php new file mode 100644 index 0000000..397ab72 --- /dev/null +++ b/new/apps/web/src/php/vendor/basuke/sveltekit-php-backend/src/PageServerEvent.php @@ -0,0 +1,29 @@ +params = $decoded['params'] ?? []; + $this->url = $decoded['url'] ?? ''; + $route = $decoded['route']['id'] ?? ''; + } + $this->route = new Route($route); + + if ($post) { + $this->post = new Post(); + } + } +} diff --git a/new/apps/web/src/php/vendor/basuke/sveltekit-php-backend/src/Post.php b/new/apps/web/src/php/vendor/basuke/sveltekit-php-backend/src/Post.php new file mode 100644 index 0000000..61fe60f --- /dev/null +++ b/new/apps/web/src/php/vendor/basuke/sveltekit-php-backend/src/Post.php @@ -0,0 +1,29 @@ +values); + } + + public function getAll($name) { + return $this->values[$name] ?? null; + } + + public function get($name) { + $values = $this->getAll($name); + return $values && count($values) > 0 ? $values[0] : null; + } + + public function offsetExists(mixed $offset): bool { return $this->getAll($offset); } + public function offsetGet(mixed $offset): mixed { return $this->get($offset); } + public function offsetSet(mixed $offset, mixed $value): void {} + public function offsetUnset(mixed $offset): void {} +} diff --git a/new/apps/web/src/php/vendor/basuke/sveltekit-php-backend/src/Route.php b/new/apps/web/src/php/vendor/basuke/sveltekit-php-backend/src/Route.php new file mode 100644 index 0000000..6218d6d --- /dev/null +++ b/new/apps/web/src/php/vendor/basuke/sveltekit-php-backend/src/Route.php @@ -0,0 +1,11 @@ +id = $id; + } +} diff --git a/new/apps/web/src/php/vendor/basuke/sveltekit-php-backend/src/functions.php b/new/apps/web/src/php/vendor/basuke/sveltekit-php-backend/src/functions.php new file mode 100644 index 0000000..7c194fc --- /dev/null +++ b/new/apps/web/src/php/vendor/basuke/sveltekit-php-backend/src/functions.php @@ -0,0 +1,15 @@ +realpath = realpath($opened_path) ?: $opened_path; + $opened_path = $this->realpath; + $this->handle = fopen($this->realpath, $mode); + $this->position = 0; + + return (bool) $this->handle; + } + + public function stream_read($count) + { + $data = fread($this->handle, $count); + + if ($this->position === 0) { + $data = preg_replace('{^#!.*\r?\n}', '', $data); + } + + $this->position += strlen($data); + + return $data; + } + + public function stream_cast($castAs) + { + return $this->handle; + } + + public function stream_close() + { + fclose($this->handle); + } + + public function stream_lock($operation) + { + return $operation ? flock($this->handle, $operation) : true; + } + + public function stream_seek($offset, $whence) + { + if (0 === fseek($this->handle, $offset, $whence)) { + $this->position = ftell($this->handle); + return true; + } + + return false; + } + + public function stream_tell() + { + return $this->position; + } + + public function stream_eof() + { + return feof($this->handle); + } + + public function stream_stat() + { + return array(); + } + + public function stream_set_option($option, $arg1, $arg2) + { + return true; + } + + public function url_stat($path, $flags) + { + $path = substr($path, 17); + if (file_exists($path)) { + return stat($path); + } + + return false; + } + } + } + + if ( + (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true)) + || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) + ) { + return include("phpvfscomposer://" . __DIR__ . '/..'.'/phpstan/phpstan/phpstan'); + } +} + +return include __DIR__ . '/..'.'/phpstan/phpstan/phpstan'; diff --git a/new/apps/web/src/php/vendor/bin/phpstan.phar b/new/apps/web/src/php/vendor/bin/phpstan.phar new file mode 100755 index 0000000..fecf96f --- /dev/null +++ b/new/apps/web/src/php/vendor/bin/phpstan.phar @@ -0,0 +1,119 @@ +#!/usr/bin/env php +realpath = realpath($opened_path) ?: $opened_path; + $opened_path = $this->realpath; + $this->handle = fopen($this->realpath, $mode); + $this->position = 0; + + return (bool) $this->handle; + } + + public function stream_read($count) + { + $data = fread($this->handle, $count); + + if ($this->position === 0) { + $data = preg_replace('{^#!.*\r?\n}', '', $data); + } + + $this->position += strlen($data); + + return $data; + } + + public function stream_cast($castAs) + { + return $this->handle; + } + + public function stream_close() + { + fclose($this->handle); + } + + public function stream_lock($operation) + { + return $operation ? flock($this->handle, $operation) : true; + } + + public function stream_seek($offset, $whence) + { + if (0 === fseek($this->handle, $offset, $whence)) { + $this->position = ftell($this->handle); + return true; + } + + return false; + } + + public function stream_tell() + { + return $this->position; + } + + public function stream_eof() + { + return feof($this->handle); + } + + public function stream_stat() + { + return array(); + } + + public function stream_set_option($option, $arg1, $arg2) + { + return true; + } + + public function url_stat($path, $flags) + { + $path = substr($path, 17); + if (file_exists($path)) { + return stat($path); + } + + return false; + } + } + } + + if ( + (function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true)) + || (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper')) + ) { + return include("phpvfscomposer://" . __DIR__ . '/..'.'/phpstan/phpstan/phpstan.phar'); + } +} + +return include __DIR__ . '/..'.'/phpstan/phpstan/phpstan.phar'; diff --git a/new/apps/web/src/php/vendor/composer/ClassLoader.php b/new/apps/web/src/php/vendor/composer/ClassLoader.php new file mode 100644 index 0000000..7824d8f --- /dev/null +++ b/new/apps/web/src/php/vendor/composer/ClassLoader.php @@ -0,0 +1,579 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see https://www.php-fig.org/psr/psr-0/ + * @see https://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + /** @var \Closure(string):void */ + private static $includeFile; + + /** @var string|null */ + private $vendorDir; + + // PSR-4 + /** + * @var array> + */ + private $prefixLengthsPsr4 = array(); + /** + * @var array> + */ + private $prefixDirsPsr4 = array(); + /** + * @var list + */ + private $fallbackDirsPsr4 = array(); + + // PSR-0 + /** + * List of PSR-0 prefixes + * + * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2'))) + * + * @var array>> + */ + private $prefixesPsr0 = array(); + /** + * @var list + */ + private $fallbackDirsPsr0 = array(); + + /** @var bool */ + private $useIncludePath = false; + + /** + * @var array + */ + private $classMap = array(); + + /** @var bool */ + private $classMapAuthoritative = false; + + /** + * @var array + */ + private $missingClasses = array(); + + /** @var string|null */ + private $apcuPrefix; + + /** + * @var array + */ + private static $registeredLoaders = array(); + + /** + * @param string|null $vendorDir + */ + public function __construct($vendorDir = null) + { + $this->vendorDir = $vendorDir; + self::initializeIncludeClosure(); + } + + /** + * @return array> + */ + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); + } + + return array(); + } + + /** + * @return array> + */ + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + /** + * @return list + */ + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + /** + * @return list + */ + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + /** + * @return array Array of classname => path + */ + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + * + * @return void + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param list|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + * + * @return void + */ + public function add($prefix, $paths, $prepend = false) + { + $paths = (array) $paths; + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + * + * @return void + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + $paths = (array) $paths; + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param list|string $paths The PSR-0 base directories + * + * @return void + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + * + * @return void + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + * + * @return void + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + * + * @return void + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * APCu prefix to use to cache found/not-found classes, if the extension is enabled. + * + * @param string|null $apcuPrefix + * + * @return void + */ + public function setApcuPrefix($apcuPrefix) + { + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; + } + + /** + * The APCu prefix in use, or null if APCu caching is not enabled. + * + * @return string|null + */ + public function getApcuPrefix() + { + return $this->apcuPrefix; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + * + * @return void + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + + if (null === $this->vendorDir) { + return; + } + + if ($prepend) { + self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; + } else { + unset(self::$registeredLoaders[$this->vendorDir]); + self::$registeredLoaders[$this->vendorDir] = $this; + } + } + + /** + * Unregisters this instance as an autoloader. + * + * @return void + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + + if (null !== $this->vendorDir) { + unset(self::$registeredLoaders[$this->vendorDir]); + } + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return true|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + $includeFile = self::$includeFile; + $includeFile($file); + + return true; + } + + return null; + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { + return false; + } + if (null !== $this->apcuPrefix) { + $file = apcu_fetch($this->apcuPrefix.$class, $hit); + if ($hit) { + return $file; + } + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if (false === $file && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if (null !== $this->apcuPrefix) { + apcu_add($this->apcuPrefix.$class, $file); + } + + if (false === $file) { + // Remember that this class does not exist. + $this->missingClasses[$class] = true; + } + + return $file; + } + + /** + * Returns the currently registered loaders keyed by their corresponding vendor directories. + * + * @return array + */ + public static function getRegisteredLoaders() + { + return self::$registeredLoaders; + } + + /** + * @param string $class + * @param string $ext + * @return string|false + */ + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + $subPath = $class; + while (false !== $lastPos = strrpos($subPath, '\\')) { + $subPath = substr($subPath, 0, $lastPos); + $search = $subPath . '\\'; + if (isset($this->prefixDirsPsr4[$search])) { + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); + foreach ($this->prefixDirsPsr4[$search] as $dir) { + if (file_exists($file = $dir . $pathEnd)) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + + return false; + } + + /** + * @return void + */ + private static function initializeIncludeClosure() + { + if (self::$includeFile !== null) { + return; + } + + /** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + * + * @param string $file + * @return void + */ + self::$includeFile = \Closure::bind(static function($file) { + include $file; + }, null, null); + } +} diff --git a/new/apps/web/src/php/vendor/composer/InstalledVersions.php b/new/apps/web/src/php/vendor/composer/InstalledVersions.php new file mode 100644 index 0000000..07b32ed --- /dev/null +++ b/new/apps/web/src/php/vendor/composer/InstalledVersions.php @@ -0,0 +1,362 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer; + +use Composer\Autoload\ClassLoader; +use Composer\Semver\VersionParser; + +/** + * This class is copied in every Composer installed project and available to all + * + * See also https://getcomposer.org/doc/07-runtime.md#installed-versions + * + * To require its presence, you can require `composer-runtime-api ^2.0` + * + * @final + */ +class InstalledVersions +{ + /** + * @var mixed[]|null + * @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array}|array{}|null + */ + private static $installed; + + /** + * @var bool|null + */ + private static $canGetVendors; + + /** + * @var array[] + * @psalm-var array}> + */ + private static $installedByVendor = array(); + + /** + * Returns a list of all package names which are present, either by being installed, replaced or provided + * + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackages() + { + $packages = array(); + foreach (self::getInstalled() as $installed) { + $packages[] = array_keys($installed['versions']); + } + + if (1 === \count($packages)) { + return $packages[0]; + } + + return array_keys(array_flip(\call_user_func_array('array_merge', $packages))); + } + + /** + * Returns a list of all package names with a specific type e.g. 'library' + * + * @param string $type + * @return string[] + * @psalm-return list + */ + public static function getInstalledPackagesByType($type) + { + $packagesByType = array(); + + foreach (self::getInstalled() as $installed) { + foreach ($installed['versions'] as $name => $package) { + if (isset($package['type']) && $package['type'] === $type) { + $packagesByType[] = $name; + } + } + } + + return $packagesByType; + } + + /** + * Checks whether the given package is installed + * + * This also returns true if the package name is provided or replaced by another package + * + * @param string $packageName + * @param bool $includeDevRequirements + * @return bool + */ + public static function isInstalled($packageName, $includeDevRequirements = true) + { + foreach (self::getInstalled() as $installed) { + if (isset($installed['versions'][$packageName])) { + return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false; + } + } + + return false; + } + + /** + * Checks whether the given package satisfies a version constraint + * + * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call: + * + * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3') + * + * @param VersionParser $parser Install composer/semver to have access to this class and functionality + * @param string $packageName + * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package + * @return bool + */ + public static function satisfies(VersionParser $parser, $packageName, $constraint) + { + $constraint = $parser->parseConstraints((string) $constraint); + $provided = $parser->parseConstraints(self::getVersionRanges($packageName)); + + return $provided->matches($constraint); + } + + /** + * Returns a version constraint representing all the range(s) which are installed for a given package + * + * It is easier to use this via isInstalled() with the $constraint argument if you need to check + * whether a given version of a package is installed, and not just whether it exists + * + * @param string $packageName + * @return string Version constraint usable with composer/semver + */ + public static function getVersionRanges($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + $ranges = array(); + if (isset($installed['versions'][$packageName]['pretty_version'])) { + $ranges[] = $installed['versions'][$packageName]['pretty_version']; + } + if (array_key_exists('aliases', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']); + } + if (array_key_exists('replaced', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']); + } + if (array_key_exists('provided', $installed['versions'][$packageName])) { + $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']); + } + + return implode(' || ', $ranges); + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['version'])) { + return null; + } + + return $installed['versions'][$packageName]['version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present + */ + public static function getPrettyVersion($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['pretty_version'])) { + return null; + } + + return $installed['versions'][$packageName]['pretty_version']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference + */ + public static function getReference($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + if (!isset($installed['versions'][$packageName]['reference'])) { + return null; + } + + return $installed['versions'][$packageName]['reference']; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @param string $packageName + * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path. + */ + public static function getInstallPath($packageName) + { + foreach (self::getInstalled() as $installed) { + if (!isset($installed['versions'][$packageName])) { + continue; + } + + return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null; + } + + throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed'); + } + + /** + * @return array + * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool} + */ + public static function getRootPackage() + { + $installed = self::getInstalled(); + + return $installed[0]['root']; + } + + /** + * Returns the raw installed.php data for custom implementations + * + * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. + * @return array[] + * @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} + */ + public static function getRawData() + { + @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED); + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + self::$installed = include __DIR__ . '/installed.php'; + } else { + self::$installed = array(); + } + } + + return self::$installed; + } + + /** + * Returns the raw data of all installed.php which are currently loaded for custom implementations + * + * @return array[] + * @psalm-return list}> + */ + public static function getAllRawData() + { + return self::getInstalled(); + } + + /** + * Lets you reload the static array from another file + * + * This is only useful for complex integrations in which a project needs to use + * this class but then also needs to execute another project's autoloader in process, + * and wants to ensure both projects have access to their version of installed.php. + * + * A typical case would be PHPUnit, where it would need to make sure it reads all + * the data it needs from this class, then call reload() with + * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure + * the project in which it runs can then also use this class safely, without + * interference between PHPUnit's dependencies and the project's dependencies. + * + * @param array[] $data A vendor/composer/installed.php data set + * @return void + * + * @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $data + */ + public static function reload($data) + { + self::$installed = $data; + self::$installedByVendor = array(); + } + + /** + * @return array[] + * @psalm-return list}> + */ + private static function getInstalled() + { + if (null === self::$canGetVendors) { + self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders'); + } + + $installed = array(); + $copiedLocalDir = false; + + if (self::$canGetVendors) { + foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) { + if (isset(self::$installedByVendor[$vendorDir])) { + $installed[] = self::$installedByVendor[$vendorDir]; + } elseif (is_file($vendorDir.'/composer/installed.php')) { + /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ + $required = require $vendorDir.'/composer/installed.php'; + self::$installedByVendor[$vendorDir] = $required; + $installed[] = $required; + if (strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { + self::$installed = $required; + $copiedLocalDir = true; + } + } + } + } + + if (null === self::$installed) { + // only require the installed.php file if this file is loaded from its dumped location, + // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 + if (substr(__DIR__, -8, 1) !== 'C') { + /** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array} $required */ + $required = require __DIR__ . '/installed.php'; + self::$installed = $required; + } else { + self::$installed = array(); + } + } + + if (self::$installed !== array() && !$copiedLocalDir) { + $installed[] = self::$installed; + } + + return $installed; + } +} diff --git a/new/apps/web/src/php/vendor/composer/LICENSE b/new/apps/web/src/php/vendor/composer/LICENSE new file mode 100644 index 0000000..f27399a --- /dev/null +++ b/new/apps/web/src/php/vendor/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) Nils Adermann, Jordi Boggiano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/new/apps/web/src/php/vendor/composer/autoload_classmap.php b/new/apps/web/src/php/vendor/composer/autoload_classmap.php new file mode 100644 index 0000000..0fb0a2c --- /dev/null +++ b/new/apps/web/src/php/vendor/composer/autoload_classmap.php @@ -0,0 +1,10 @@ + $vendorDir . '/composer/InstalledVersions.php', +); diff --git a/new/apps/web/src/php/vendor/composer/autoload_files.php b/new/apps/web/src/php/vendor/composer/autoload_files.php new file mode 100644 index 0000000..7497dfb --- /dev/null +++ b/new/apps/web/src/php/vendor/composer/autoload_files.php @@ -0,0 +1,11 @@ + $vendorDir . '/phpstan/phpstan/bootstrap.php', + '629d555ade6f293dd904e9594675355a' => $vendorDir . '/basuke/sveltekit-php-backend/src/functions.php', +); diff --git a/new/apps/web/src/php/vendor/composer/autoload_namespaces.php b/new/apps/web/src/php/vendor/composer/autoload_namespaces.php new file mode 100644 index 0000000..15a2ff3 --- /dev/null +++ b/new/apps/web/src/php/vendor/composer/autoload_namespaces.php @@ -0,0 +1,9 @@ + array($vendorDir . '/phpstan/phpstan-strict-rules/src'), + 'Basuke\\SvelteKit\\' => array($vendorDir . '/basuke/sveltekit-php-backend/src'), +); diff --git a/new/apps/web/src/php/vendor/composer/autoload_real.php b/new/apps/web/src/php/vendor/composer/autoload_real.php new file mode 100644 index 0000000..b87979e --- /dev/null +++ b/new/apps/web/src/php/vendor/composer/autoload_real.php @@ -0,0 +1,50 @@ +register(true); + + $filesToLoad = \Composer\Autoload\ComposerStaticInit1922d18568d1e5b4a890afdb35524094::$files; + $requireFile = \Closure::bind(static function ($fileIdentifier, $file) { + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + + require $file; + } + }, null, null); + foreach ($filesToLoad as $fileIdentifier => $file) { + $requireFile($fileIdentifier, $file); + } + + return $loader; + } +} diff --git a/new/apps/web/src/php/vendor/composer/autoload_static.php b/new/apps/web/src/php/vendor/composer/autoload_static.php new file mode 100644 index 0000000..0ec01e2 --- /dev/null +++ b/new/apps/web/src/php/vendor/composer/autoload_static.php @@ -0,0 +1,49 @@ + __DIR__ . '/..' . '/phpstan/phpstan/bootstrap.php', + '629d555ade6f293dd904e9594675355a' => __DIR__ . '/..' . '/basuke/sveltekit-php-backend/src/functions.php', + ); + + public static $prefixLengthsPsr4 = array ( + 'P' => + array ( + 'PHPStan\\' => 8, + ), + 'B' => + array ( + 'Basuke\\SvelteKit\\' => 17, + ), + ); + + public static $prefixDirsPsr4 = array ( + 'PHPStan\\' => + array ( + 0 => __DIR__ . '/..' . '/phpstan/phpstan-strict-rules/src', + ), + 'Basuke\\SvelteKit\\' => + array ( + 0 => __DIR__ . '/..' . '/basuke/sveltekit-php-backend/src', + ), + ); + + public static $classMap = array ( + 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->prefixLengthsPsr4 = ComposerStaticInit1922d18568d1e5b4a890afdb35524094::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInit1922d18568d1e5b4a890afdb35524094::$prefixDirsPsr4; + $loader->classMap = ComposerStaticInit1922d18568d1e5b4a890afdb35524094::$classMap; + + }, null, ClassLoader::class); + } +} diff --git a/new/apps/web/src/php/vendor/composer/installed.json b/new/apps/web/src/php/vendor/composer/installed.json new file mode 100644 index 0000000..4fe0046 --- /dev/null +++ b/new/apps/web/src/php/vendor/composer/installed.json @@ -0,0 +1,175 @@ +{ + "packages": [ + { + "name": "basuke/sveltekit-php-backend", + "version": "1.0.0", + "version_normalized": "1.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/basuke/sveltekit-php-backend.git", + "reference": "a27c0c0208a8dc33a1f99d8dcfc72fd1302f0cb7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/basuke/sveltekit-php-backend/zipball/a27c0c0208a8dc33a1f99d8dcfc72fd1302f0cb7", + "reference": "a27c0c0208a8dc33a1f99d8dcfc72fd1302f0cb7", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "time": "2023-05-21T17:15:35+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Basuke\\SvelteKit\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Basuke Suzuki", + "email": "basuke@mac.com" + } + ], + "description": "Supplemental package to support SvelteKit PHP Backend Vite Plugin", + "homepage": "https://github.com/basuke/sveltekit-php-backend", + "keywords": [ + "SvelteKit", + "backend", + "svelte", + "vite" + ], + "support": { + "issues": "https://github.com/basuke/sveltekit-php-backend/issues", + "source": "https://github.com/basuke/sveltekit-php-backend/tree/1.0.0" + }, + "install-path": "../basuke/sveltekit-php-backend" + }, + { + "name": "phpstan/phpstan", + "version": "1.12.7", + "version_normalized": "1.12.7.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "dc2b9976bd8b0f84ec9b0e50cc35378551de7af0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/dc2b9976bd8b0f84ec9b0e50cc35378551de7af0", + "reference": "dc2b9976bd8b0f84ec9b0e50cc35378551de7af0", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "time": "2024-10-18T11:12:07+00:00", + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "installation-source": "dist", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "install-path": "../phpstan/phpstan" + }, + { + "name": "phpstan/phpstan-strict-rules", + "version": "1.6.1", + "version_normalized": "1.6.1.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan-strict-rules.git", + "reference": "daeec748b53de80a97498462513066834ec28f8b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/daeec748b53de80a97498462513066834ec28f8b", + "reference": "daeec748b53de80a97498462513066834ec28f8b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.12.4" + }, + "require-dev": { + "nikic/php-parser": "^4.13.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-deprecation-rules": "^1.1", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^9.5" + }, + "time": "2024-09-20T14:04:44+00:00", + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "rules.neon" + ] + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Extra strict and opinionated rules for PHPStan", + "support": { + "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.6.1" + }, + "install-path": "../phpstan/phpstan-strict-rules" + } + ], + "dev": true, + "dev-package-names": [ + "phpstan/phpstan", + "phpstan/phpstan-strict-rules" + ] +} diff --git a/new/apps/web/src/php/vendor/composer/installed.php b/new/apps/web/src/php/vendor/composer/installed.php new file mode 100644 index 0000000..6cd98c4 --- /dev/null +++ b/new/apps/web/src/php/vendor/composer/installed.php @@ -0,0 +1,50 @@ + array( + 'name' => 'spec-ify/specified', + 'pretty_version' => '2.x-dev', + 'version' => '2.9999999.9999999.9999999-dev', + 'reference' => 'e6fe4231819277e3420b0fbe1d27b99b567967b2', + 'type' => 'project', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'dev' => true, + ), + 'versions' => array( + 'basuke/sveltekit-php-backend' => array( + 'pretty_version' => '1.0.0', + 'version' => '1.0.0.0', + 'reference' => 'a27c0c0208a8dc33a1f99d8dcfc72fd1302f0cb7', + 'type' => 'library', + 'install_path' => __DIR__ . '/../basuke/sveltekit-php-backend', + 'aliases' => array(), + 'dev_requirement' => false, + ), + 'phpstan/phpstan' => array( + 'pretty_version' => '1.12.7', + 'version' => '1.12.7.0', + 'reference' => 'dc2b9976bd8b0f84ec9b0e50cc35378551de7af0', + 'type' => 'library', + 'install_path' => __DIR__ . '/../phpstan/phpstan', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'phpstan/phpstan-strict-rules' => array( + 'pretty_version' => '1.6.1', + 'version' => '1.6.1.0', + 'reference' => 'daeec748b53de80a97498462513066834ec28f8b', + 'type' => 'phpstan-extension', + 'install_path' => __DIR__ . '/../phpstan/phpstan-strict-rules', + 'aliases' => array(), + 'dev_requirement' => true, + ), + 'spec-ify/specified' => array( + 'pretty_version' => '2.x-dev', + 'version' => '2.9999999.9999999.9999999-dev', + 'reference' => 'e6fe4231819277e3420b0fbe1d27b99b567967b2', + 'type' => 'project', + 'install_path' => __DIR__ . '/../../', + 'aliases' => array(), + 'dev_requirement' => false, + ), + ), +); diff --git a/new/apps/web/src/php/vendor/composer/platform_check.php b/new/apps/web/src/php/vendor/composer/platform_check.php new file mode 100644 index 0000000..adfb472 --- /dev/null +++ b/new/apps/web/src/php/vendor/composer/platform_check.php @@ -0,0 +1,26 @@ += 80000)) { + $issues[] = 'Your Composer dependencies require a PHP version ">= 8.0.0". You are running ' . PHP_VERSION . '.'; +} + +if ($issues) { + if (!headers_sent()) { + header('HTTP/1.1 500 Internal Server Error'); + } + if (!ini_get('display_errors')) { + if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { + fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL); + } elseif (!headers_sent()) { + echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL; + } + } + trigger_error( + 'Composer detected issues in your platform: ' . implode(' ', $issues), + E_USER_ERROR + ); +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/.editorconfig b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/.editorconfig new file mode 100644 index 0000000..5d66bc4 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/.editorconfig @@ -0,0 +1,27 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +trim_trailing_whitespace = true + +[*.{php,phpt}] +indent_style = tab +indent_size = 4 + +[*.xml] +indent_style = tab +indent_size = 4 + +[*.neon] +indent_style = tab +indent_size = 4 + +[*.{yaml,yml}] +indent_style = space +indent_size = 2 + +[composer.json] +indent_style = tab +indent_size = 4 diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/LICENSE b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/LICENSE new file mode 100644 index 0000000..d005374 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2016 Ondřej Mirtes + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/README.md b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/README.md new file mode 100644 index 0000000..9431011 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/README.md @@ -0,0 +1,103 @@ +# Extra strict and opinionated rules for PHPStan + +[![Build](https://github.com/phpstan/phpstan-strict-rules/workflows/Build/badge.svg)](https://github.com/phpstan/phpstan-strict-rules/actions) +[![Latest Stable Version](https://poser.pugx.org/phpstan/phpstan-strict-rules/v/stable)](https://packagist.org/packages/phpstan/phpstan-strict-rules) +[![License](https://poser.pugx.org/phpstan/phpstan-strict-rules/license)](https://packagist.org/packages/phpstan/phpstan-strict-rules) + +[PHPStan](https://phpstan.org/) focuses on finding bugs in your code. But in PHP there's a lot of leeway in how stuff can be written. This repository contains additional rules that revolve around strictly and strongly typed code with no loose casting for those who want additional safety in extremely defensive programming: + +* Require booleans in `if`, `elseif`, ternary operator, after `!`, and on both sides of `&&` and `||`. +* Require numeric operands or arrays in `+` and numeric operands in `-`/`*`/`/`/`**`/`%`. +* Require numeric operand in `$var++`, `$var--`, `++$var`and `--$var`. +* These functions contain a `$strict` parameter for better type safety, it must be set to `true`: + * `in_array` (3rd parameter) + * `array_search` (3rd parameter) + * `array_keys` (3rd parameter; only if the 2nd parameter `$search_value` is provided) + * `base64_decode` (2nd parameter) +* Variables assigned in `while` loop condition and `for` loop initial assignment cannot be used after the loop. +* Variables set in foreach that's always looped thanks to non-empty arrays cannot be used after the loop. +* Types in `switch` condition and `case` value must match. PHP compares them loosely by default and that can lead to unexpected results. +* Check that statically declared methods are called statically. +* Disallow `empty()` - it's a very loose comparison (see [manual](https://php.net/empty)), it's recommended to use more strict one. +* Disallow short ternary operator (`?:`) - implies weak comparison, it's recommended to use null coalesce operator (`??`) or ternary operator with strict condition. +* Disallow variable variables (`$$foo`, `$this->$method()` etc.) +* Disallow overwriting variables with foreach key and value variables +* Always true `instanceof`, type-checking `is_*` functions and strict comparisons `===`/`!==`. These checks can be turned off by setting `checkAlwaysTrueInstanceof`/`checkAlwaysTrueCheckTypeFunctionCall`/`checkAlwaysTrueStrictComparison` to false. +* Correct case for referenced and called function names. +* Correct case for inherited and implemented method names. +* Contravariance for parameter types and covariance for return types in inherited methods (also known as Liskov substitution principle - LSP) +* Check LSP even for static methods +* Require calling parent constructor +* Disallow usage of backtick operator (`` $ls = `ls -la` ``) +* Closure should use `$this` directly instead of using `$this` variable indirectly + +Additional rules are coming in subsequent releases! + + +## Installation + +To use this extension, require it in [Composer](https://getcomposer.org/): + +``` +composer require --dev phpstan/phpstan-strict-rules +``` + +If you also install [phpstan/extension-installer](https://github.com/phpstan/extension-installer) then you're all set! + +
+ Manual installation + +If you don't want to use `phpstan/extension-installer`, include rules.neon in your project's PHPStan config: + +``` +includes: + - vendor/phpstan/phpstan-strict-rules/rules.neon +``` +
+ +## Disabling rules + +You can disable rules using configuration parameters: + +```neon +parameters: + strictRules: + disallowedLooseComparison: false + booleansInConditions: false + uselessCast: false + requireParentConstructorCall: false + disallowedConstructs: false + overwriteVariablesWithLoop: false + closureUsesThis: false + matchingInheritedMethodNames: false + numericOperandsInArithmeticOperators: false + strictCalls: false + switchConditionsMatchingType: false + noVariableVariables: false + strictArrayFilter: false +``` + +Aside from introducing new custom rules, phpstan-strict-rules also [change the default values of some configuration parameters](https://github.com/phpstan/phpstan-strict-rules/blob/1.6.x/rules.neon#L1) that are present in PHPStan itself. These parameters are [documented on phpstan.org](https://phpstan.org/config-reference#stricter-analysis). + +## Enabling rules one-by-one + +If you don't want to start using all the available strict rules at once but only one or two, you can! + +You can disable all rules from the included `rules.neon` with: + +```neon +parameters: + strictRules: + allRules: false +``` + +Then you can re-enable individual rules with configuration parameters: + +```neon +parameters: + strictRules: + allRules: false + booleansInConditions: true +``` + +Even with `strictRules.allRules` set to `false`, part of this package is still in effect. That's because phpstan-strict-rules also [change the default values of some configuration parameters](https://github.com/phpstan/phpstan-strict-rules/blob/1.6.x/rules.neon#L1) that are present in PHPStan itself. These parameters are [documented on phpstan.org](https://phpstan.org/config-reference#stricter-analysis). diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/composer.json b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/composer.json new file mode 100644 index 0000000..4e8399e --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/composer.json @@ -0,0 +1,44 @@ +{ + "name": "phpstan/phpstan-strict-rules", + "type": "phpstan-extension", + "description": "Extra strict and opinionated rules for PHPStan", + "license": [ + "MIT" + ], + "require": { + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.12.4" + }, + "require-dev": { + "nikic/php-parser": "^4.13.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-deprecation-rules": "^1.1", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^9.5" + }, + "config": { + "platform": { + "php": "7.4.6" + }, + "sort-packages": true + }, + "extra": { + "phpstan": { + "includes": [ + "rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": "src/" + } + }, + "autoload-dev": { + "classmap": [ + "tests/" + ] + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/rules.neon b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/rules.neon new file mode 100644 index 0000000..e9be35a --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/rules.neon @@ -0,0 +1,279 @@ +parameters: + polluteScopeWithLoopInitialAssignments: false + polluteScopeWithAlwaysIterableForeach: false + checkAlwaysTrueCheckTypeFunctionCall: true + checkAlwaysTrueInstanceof: true + checkAlwaysTrueStrictComparison: true + checkAlwaysTrueLooseComparison: true + checkDynamicProperties: %featureToggles.bleedingEdge% + checkExplicitMixedMissingReturn: true + checkFunctionNameCase: true + checkInternalClassCaseSensitivity: true + reportMaybesInMethodSignatures: true + reportStaticMethodSignatures: true + reportMaybesInPropertyPhpDocTypes: true + reportWrongPhpDocTypeInVarTag: %featureToggles.bleedingEdge% + featureToggles: + illegalConstructorMethodCall: %featureToggles.bleedingEdge% + strictRules: + allRules: true + disallowedLooseComparison: [%strictRules.allRules%, %featureToggles.bleedingEdge%] + booleansInConditions: %strictRules.allRules% + uselessCast: %strictRules.allRules% + requireParentConstructorCall: %strictRules.allRules% + disallowedConstructs: %strictRules.allRules% + overwriteVariablesWithLoop: %strictRules.allRules% + closureUsesThis: %strictRules.allRules% + matchingInheritedMethodNames: %strictRules.allRules% + numericOperandsInArithmeticOperators: %strictRules.allRules% + strictCalls: %strictRules.allRules% + switchConditionsMatchingType: %strictRules.allRules% + noVariableVariables: %strictRules.allRules% + strictArrayFilter: [%strictRules.allRules%, %featureToggles.bleedingEdge%] + +parametersSchema: + strictRules: structure([ + allRules: anyOf(bool(), arrayOf(bool())), + disallowedLooseComparison: anyOf(bool(), arrayOf(bool())), + booleansInConditions: anyOf(bool(), arrayOf(bool())) + uselessCast: anyOf(bool(), arrayOf(bool())) + requireParentConstructorCall: anyOf(bool(), arrayOf(bool())) + disallowedConstructs: anyOf(bool(), arrayOf(bool())) + overwriteVariablesWithLoop: anyOf(bool(), arrayOf(bool())) + closureUsesThis: anyOf(bool(), arrayOf(bool())) + matchingInheritedMethodNames: anyOf(bool(), arrayOf(bool())) + numericOperandsInArithmeticOperators: anyOf(bool(), arrayOf(bool())) + strictCalls: anyOf(bool(), arrayOf(bool())) + switchConditionsMatchingType: anyOf(bool(), arrayOf(bool())) + noVariableVariables: anyOf(bool(), arrayOf(bool())) + strictArrayFilter: anyOf(bool(), arrayOf(bool())) + ]) + +conditionalTags: + PHPStan\Rules\DisallowedConstructs\DisallowedLooseComparisonRule: + phpstan.rules.rule: %strictRules.disallowedLooseComparison% + PHPStan\Rules\BooleansInConditions\BooleanInBooleanAndRule: + phpstan.rules.rule: %strictRules.booleansInConditions% + PHPStan\Rules\BooleansInConditions\BooleanInBooleanNotRule: + phpstan.rules.rule: %strictRules.booleansInConditions% + PHPStan\Rules\BooleansInConditions\BooleanInBooleanOrRule: + phpstan.rules.rule: %strictRules.booleansInConditions% + PHPStan\Rules\BooleansInConditions\BooleanInElseIfConditionRule: + phpstan.rules.rule: %strictRules.booleansInConditions% + PHPStan\Rules\BooleansInConditions\BooleanInIfConditionRule: + phpstan.rules.rule: %strictRules.booleansInConditions% + PHPStan\Rules\BooleansInConditions\BooleanInTernaryOperatorRule: + phpstan.rules.rule: %strictRules.booleansInConditions% + PHPStan\Rules\Cast\UselessCastRule: + phpstan.rules.rule: %strictRules.uselessCast% + PHPStan\Rules\Classes\RequireParentConstructCallRule: + phpstan.rules.rule: %strictRules.requireParentConstructorCall% + PHPStan\Rules\DisallowedConstructs\DisallowedBacktickRule: + phpstan.rules.rule: %strictRules.disallowedConstructs% + PHPStan\Rules\DisallowedConstructs\DisallowedEmptyRule: + phpstan.rules.rule: %strictRules.disallowedConstructs% + PHPStan\Rules\DisallowedConstructs\DisallowedImplicitArrayCreationRule: + phpstan.rules.rule: %strictRules.disallowedConstructs% + PHPStan\Rules\DisallowedConstructs\DisallowedShortTernaryRule: + phpstan.rules.rule: %strictRules.disallowedConstructs% + PHPStan\Rules\ForeachLoop\OverwriteVariablesWithForeachRule: + phpstan.rules.rule: %strictRules.overwriteVariablesWithLoop% + PHPStan\Rules\ForLoop\OverwriteVariablesWithForLoopInitRule: + phpstan.rules.rule: %strictRules.overwriteVariablesWithLoop% + PHPStan\Rules\Functions\ArrayFilterStrictRule: + phpstan.rules.rule: %strictRules.strictArrayFilter% + PHPStan\Rules\Functions\ClosureUsesThisRule: + phpstan.rules.rule: %strictRules.closureUsesThis% + PHPStan\Rules\Methods\WrongCaseOfInheritedMethodRule: + phpstan.rules.rule: %strictRules.matchingInheritedMethodNames% + PHPStan\Rules\Operators\OperandInArithmeticPostDecrementRule: + phpstan.rules.rule: %strictRules.numericOperandsInArithmeticOperators% + PHPStan\Rules\Operators\OperandInArithmeticPostIncrementRule: + phpstan.rules.rule: %strictRules.numericOperandsInArithmeticOperators% + PHPStan\Rules\Operators\OperandInArithmeticPreDecrementRule: + phpstan.rules.rule: %strictRules.numericOperandsInArithmeticOperators% + PHPStan\Rules\Operators\OperandInArithmeticPreIncrementRule: + phpstan.rules.rule: %strictRules.numericOperandsInArithmeticOperators% + PHPStan\Rules\Operators\OperandsInArithmeticAdditionRule: + phpstan.rules.rule: %strictRules.numericOperandsInArithmeticOperators% + PHPStan\Rules\Operators\OperandsInArithmeticDivisionRule: + phpstan.rules.rule: %strictRules.numericOperandsInArithmeticOperators% + PHPStan\Rules\Operators\OperandsInArithmeticExponentiationRule: + phpstan.rules.rule: %strictRules.numericOperandsInArithmeticOperators% + PHPStan\Rules\Operators\OperandsInArithmeticModuloRule: + phpstan.rules.rule: %strictRules.numericOperandsInArithmeticOperators% + PHPStan\Rules\Operators\OperandsInArithmeticMultiplicationRule: + phpstan.rules.rule: %strictRules.numericOperandsInArithmeticOperators% + PHPStan\Rules\Operators\OperandsInArithmeticSubtractionRule: + phpstan.rules.rule: %strictRules.numericOperandsInArithmeticOperators% + PHPStan\Rules\StrictCalls\DynamicCallOnStaticMethodsRule: + phpstan.rules.rule: %strictRules.strictCalls% + PHPStan\Rules\StrictCalls\DynamicCallOnStaticMethodsCallableRule: + phpstan.rules.rule: %strictRules.strictCalls% + PHPStan\Rules\StrictCalls\StrictFunctionCallsRule: + phpstan.rules.rule: %strictRules.strictCalls% + PHPStan\Rules\SwitchConditions\MatchingTypeInSwitchCaseConditionRule: + phpstan.rules.rule: %strictRules.switchConditionsMatchingType% + PHPStan\Rules\VariableVariables\VariableMethodCallRule: + phpstan.rules.rule: %strictRules.noVariableVariables% + PHPStan\Rules\VariableVariables\VariableMethodCallableRule: + phpstan.rules.rule: %strictRules.noVariableVariables% + PHPStan\Rules\VariableVariables\VariableStaticMethodCallRule: + phpstan.rules.rule: %strictRules.noVariableVariables% + PHPStan\Rules\VariableVariables\VariableStaticMethodCallableRule: + phpstan.rules.rule: %strictRules.noVariableVariables% + PHPStan\Rules\VariableVariables\VariableStaticPropertyFetchRule: + phpstan.rules.rule: %strictRules.noVariableVariables% + PHPStan\Rules\VariableVariables\VariableVariablesRule: + phpstan.rules.rule: %strictRules.noVariableVariables% + PHPStan\Rules\VariableVariables\VariablePropertyFetchRule: + phpstan.rules.rule: %strictRules.noVariableVariables% + +services: + - + class: PHPStan\Rules\BooleansInConditions\BooleanRuleHelper + + - + class: PHPStan\Rules\Operators\OperatorRuleHelper + + - + class: PHPStan\Rules\VariableVariables\VariablePropertyFetchRule + arguments: + universalObjectCratesClasses: %universalObjectCratesClasses% + + - + class: PHPStan\Rules\DisallowedConstructs\DisallowedLooseComparisonRule + + - + class: PHPStan\Rules\BooleansInConditions\BooleanInBooleanAndRule + arguments: + bleedingEdge: %featureToggles.bleedingEdge% + + - + class: PHPStan\Rules\BooleansInConditions\BooleanInBooleanNotRule + + - + class: PHPStan\Rules\BooleansInConditions\BooleanInBooleanOrRule + arguments: + bleedingEdge: %featureToggles.bleedingEdge% + + - + class: PHPStan\Rules\BooleansInConditions\BooleanInElseIfConditionRule + + - + class: PHPStan\Rules\BooleansInConditions\BooleanInIfConditionRule + + - + class: PHPStan\Rules\BooleansInConditions\BooleanInTernaryOperatorRule + + - + class: PHPStan\Rules\Cast\UselessCastRule + arguments: + treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% + treatPhpDocTypesAsCertainTip: %tips.treatPhpDocTypesAsCertain% + + - + class: PHPStan\Rules\Classes\RequireParentConstructCallRule + + - + class: PHPStan\Rules\DisallowedConstructs\DisallowedBacktickRule + + - + class: PHPStan\Rules\DisallowedConstructs\DisallowedEmptyRule + + - + class: PHPStan\Rules\DisallowedConstructs\DisallowedImplicitArrayCreationRule + + - + class: PHPStan\Rules\DisallowedConstructs\DisallowedShortTernaryRule + + - + class: PHPStan\Rules\ForeachLoop\OverwriteVariablesWithForeachRule + + - + class: PHPStan\Rules\ForLoop\OverwriteVariablesWithForLoopInitRule + + - + class: PHPStan\Rules\Functions\ArrayFilterStrictRule + arguments: + treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain% + checkNullables: %checkNullables% + treatPhpDocTypesAsCertainTip: %tips.treatPhpDocTypesAsCertain% + + - + class: PHPStan\Rules\Functions\ClosureUsesThisRule + + - + class: PHPStan\Rules\Methods\WrongCaseOfInheritedMethodRule + + - + class: PHPStan\Rules\Operators\OperandInArithmeticPostDecrementRule + + - + class: PHPStan\Rules\Operators\OperandInArithmeticPostIncrementRule + + - + class: PHPStan\Rules\Operators\OperandInArithmeticPreDecrementRule + + - + class: PHPStan\Rules\Operators\OperandInArithmeticPreIncrementRule + + - + class: PHPStan\Rules\Operators\OperandsInArithmeticAdditionRule + arguments: + bleedingEdge: %featureToggles.bleedingEdge% + + - + class: PHPStan\Rules\Operators\OperandsInArithmeticDivisionRule + arguments: + bleedingEdge: %featureToggles.bleedingEdge% + + - + class: PHPStan\Rules\Operators\OperandsInArithmeticExponentiationRule + arguments: + bleedingEdge: %featureToggles.bleedingEdge% + + - + class: PHPStan\Rules\Operators\OperandsInArithmeticModuloRule + arguments: + bleedingEdge: %featureToggles.bleedingEdge% + + - + class: PHPStan\Rules\Operators\OperandsInArithmeticMultiplicationRule + arguments: + bleedingEdge: %featureToggles.bleedingEdge% + + - + class: PHPStan\Rules\Operators\OperandsInArithmeticSubtractionRule + arguments: + bleedingEdge: %featureToggles.bleedingEdge% + + - + class: PHPStan\Rules\StrictCalls\DynamicCallOnStaticMethodsRule + + - + class: PHPStan\Rules\StrictCalls\DynamicCallOnStaticMethodsCallableRule + + - + class: PHPStan\Rules\StrictCalls\StrictFunctionCallsRule + + - + class: PHPStan\Rules\SwitchConditions\MatchingTypeInSwitchCaseConditionRule + + - + class: PHPStan\Rules\VariableVariables\VariableMethodCallRule + + - + class: PHPStan\Rules\VariableVariables\VariableMethodCallableRule + + - + class: PHPStan\Rules\VariableVariables\VariableStaticMethodCallRule + + - + class: PHPStan\Rules\VariableVariables\VariableStaticMethodCallableRule + + - + class: PHPStan\Rules\VariableVariables\VariableStaticPropertyFetchRule + + - + class: PHPStan\Rules\VariableVariables\VariableVariablesRule diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanInBooleanAndRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanInBooleanAndRule.php new file mode 100644 index 0000000..aebe8ad --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanInBooleanAndRule.php @@ -0,0 +1,64 @@ + + */ +class BooleanInBooleanAndRule implements Rule +{ + + /** @var BooleanRuleHelper */ + private $helper; + + /** @var bool */ + private $bleedingEdge; + + public function __construct(BooleanRuleHelper $helper, bool $bleedingEdge) + { + $this->helper = $helper; + $this->bleedingEdge = $bleedingEdge; + } + + public function getNodeType(): string + { + return BooleanAndNode::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $originalNode = $node->getOriginalNode(); + $messages = []; + $nodeText = $this->bleedingEdge ? $originalNode->getOperatorSigil() : '&&'; + $identifierType = $originalNode instanceof Node\Expr\BinaryOp\BooleanAnd ? 'booleanAnd' : 'logicalAnd'; + if (!$this->helper->passesAsBoolean($scope, $originalNode->left)) { + $leftType = $scope->getType($originalNode->left); + $messages[] = RuleErrorBuilder::message(sprintf( + 'Only booleans are allowed in %s, %s given on the left side.', + $nodeText, + $leftType->describe(VerbosityLevel::typeOnly()) + ))->identifier(sprintf('%s.leftNotBoolean', $identifierType))->build(); + } + + $rightScope = $node->getRightScope(); + if (!$this->helper->passesAsBoolean($rightScope, $originalNode->right)) { + $rightType = $rightScope->getType($originalNode->right); + $messages[] = RuleErrorBuilder::message(sprintf( + 'Only booleans are allowed in %s, %s given on the right side.', + $nodeText, + $rightType->describe(VerbosityLevel::typeOnly()) + ))->identifier(sprintf('%s.rightNotBoolean', $identifierType))->build(); + } + + return $messages; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanInBooleanNotRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanInBooleanNotRule.php new file mode 100644 index 0000000..6fcdd06 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanInBooleanNotRule.php @@ -0,0 +1,48 @@ + + */ +class BooleanInBooleanNotRule implements Rule +{ + + /** @var BooleanRuleHelper */ + private $helper; + + public function __construct(BooleanRuleHelper $helper) + { + $this->helper = $helper; + } + + public function getNodeType(): string + { + return BooleanNot::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if ($this->helper->passesAsBoolean($scope, $node->expr)) { + return []; + } + + $expressionType = $scope->getType($node->expr); + + return [ + RuleErrorBuilder::message(sprintf( + 'Only booleans are allowed in a negated boolean, %s given.', + $expressionType->describe(VerbosityLevel::typeOnly()) + ))->identifier('booleanNot.exprNotBoolean')->build(), + ]; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanInBooleanOrRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanInBooleanOrRule.php new file mode 100644 index 0000000..e03911c --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanInBooleanOrRule.php @@ -0,0 +1,64 @@ + + */ +class BooleanInBooleanOrRule implements Rule +{ + + /** @var BooleanRuleHelper */ + private $helper; + + /** @var bool */ + private $bleedingEdge; + + public function __construct(BooleanRuleHelper $helper, bool $bleedingEdge) + { + $this->helper = $helper; + $this->bleedingEdge = $bleedingEdge; + } + + public function getNodeType(): string + { + return BooleanOrNode::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $originalNode = $node->getOriginalNode(); + $messages = []; + $nodeText = $this->bleedingEdge ? $originalNode->getOperatorSigil() : '||'; + $identifierType = $originalNode instanceof Node\Expr\BinaryOp\BooleanOr ? 'booleanOr' : 'logicalOr'; + if (!$this->helper->passesAsBoolean($scope, $originalNode->left)) { + $leftType = $scope->getType($originalNode->left); + $messages[] = RuleErrorBuilder::message(sprintf( + 'Only booleans are allowed in %s, %s given on the left side.', + $nodeText, + $leftType->describe(VerbosityLevel::typeOnly()) + ))->identifier(sprintf('%s.leftNotBoolean', $identifierType))->build(); + } + + $rightScope = $node->getRightScope(); + if (!$this->helper->passesAsBoolean($rightScope, $originalNode->right)) { + $rightType = $rightScope->getType($originalNode->right); + $messages[] = RuleErrorBuilder::message(sprintf( + 'Only booleans are allowed in %s, %s given on the right side.', + $nodeText, + $rightType->describe(VerbosityLevel::typeOnly()) + ))->identifier(sprintf('%s.rightNotBoolean', $identifierType))->build(); + } + + return $messages; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanInElseIfConditionRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanInElseIfConditionRule.php new file mode 100644 index 0000000..2501b82 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanInElseIfConditionRule.php @@ -0,0 +1,48 @@ + + */ +class BooleanInElseIfConditionRule implements Rule +{ + + /** @var BooleanRuleHelper */ + private $helper; + + public function __construct(BooleanRuleHelper $helper) + { + $this->helper = $helper; + } + + public function getNodeType(): string + { + return ElseIf_::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if ($this->helper->passesAsBoolean($scope, $node->cond)) { + return []; + } + + $conditionExpressionType = $scope->getType($node->cond); + + return [ + RuleErrorBuilder::message(sprintf( + 'Only booleans are allowed in an elseif condition, %s given.', + $conditionExpressionType->describe(VerbosityLevel::typeOnly()) + ))->identifier('elseif.condNotBoolean')->build(), + ]; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanInIfConditionRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanInIfConditionRule.php new file mode 100644 index 0000000..5adb10e --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanInIfConditionRule.php @@ -0,0 +1,48 @@ + + */ +class BooleanInIfConditionRule implements Rule +{ + + /** @var BooleanRuleHelper */ + private $helper; + + public function __construct(BooleanRuleHelper $helper) + { + $this->helper = $helper; + } + + public function getNodeType(): string + { + return If_::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if ($this->helper->passesAsBoolean($scope, $node->cond)) { + return []; + } + + $conditionExpressionType = $scope->getType($node->cond); + + return [ + RuleErrorBuilder::message(sprintf( + 'Only booleans are allowed in an if condition, %s given.', + $conditionExpressionType->describe(VerbosityLevel::typeOnly()) + ))->identifier('if.condNotBoolean')->build(), + ]; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanInTernaryOperatorRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanInTernaryOperatorRule.php new file mode 100644 index 0000000..e1ac9cc --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanInTernaryOperatorRule.php @@ -0,0 +1,52 @@ + + */ +class BooleanInTernaryOperatorRule implements Rule +{ + + /** @var BooleanRuleHelper */ + private $helper; + + public function __construct(BooleanRuleHelper $helper) + { + $this->helper = $helper; + } + + public function getNodeType(): string + { + return Ternary::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if ($node->if === null) { + return []; // elvis ?: + } + + if ($this->helper->passesAsBoolean($scope, $node->cond)) { + return []; + } + + $conditionExpressionType = $scope->getType($node->cond); + + return [ + RuleErrorBuilder::message(sprintf( + 'Only booleans are allowed in a ternary operator condition, %s given.', + $conditionExpressionType->describe(VerbosityLevel::typeOnly()) + ))->identifier('ternary.condNotBoolean')->build(), + ]; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanRuleHelper.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanRuleHelper.php new file mode 100644 index 0000000..1e307d6 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/BooleansInConditions/BooleanRuleHelper.php @@ -0,0 +1,45 @@ +ruleLevelHelper = $ruleLevelHelper; + } + + public function passesAsBoolean(Scope $scope, Expr $expr): bool + { + $type = $scope->getType($expr); + if ($type instanceof MixedType) { + return !$type->isExplicitMixed(); + } + $typeToCheck = $this->ruleLevelHelper->findTypeToCheck( + $scope, + $expr, + '', + static function (Type $type): bool { + return $type->isBoolean()->yes(); + } + ); + $foundType = $typeToCheck->getType(); + if ($foundType instanceof ErrorType) { + return true; + } + + return $foundType->isBoolean()->yes(); + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Cast/UselessCastRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Cast/UselessCastRule.php new file mode 100644 index 0000000..99347cc --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Cast/UselessCastRule.php @@ -0,0 +1,83 @@ + + */ +class UselessCastRule implements Rule +{ + + /** @var bool */ + private $treatPhpDocTypesAsCertain; + + /** @var bool */ + private $treatPhpDocTypesAsCertainTip; + + public function __construct( + bool $treatPhpDocTypesAsCertain, + bool $treatPhpDocTypesAsCertainTip + ) + { + $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; + $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; + } + + public function getNodeType(): string + { + return Cast::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $castType = $scope->getType($node); + if ($castType instanceof ErrorType) { + return []; + } + $castType = $castType->generalize(GeneralizePrecision::lessSpecific()); + + if ($this->treatPhpDocTypesAsCertain) { + $expressionType = $scope->getType($node->expr); + } else { + $expressionType = $scope->getNativeType($node->expr); + } + if ($castType->isSuperTypeOf($expressionType)->yes()) { + $addTip = function (RuleErrorBuilder $ruleErrorBuilder) use ($scope, $node, $castType): RuleErrorBuilder { + if (!$this->treatPhpDocTypesAsCertain) { + return $ruleErrorBuilder; + } + + $expressionTypeWithoutPhpDoc = $scope->getNativeType($node->expr); + if ($castType->isSuperTypeOf($expressionTypeWithoutPhpDoc)->yes()) { + return $ruleErrorBuilder; + } + + if (!$this->treatPhpDocTypesAsCertainTip) { + return $ruleErrorBuilder; + } + + return $ruleErrorBuilder->treatPhpDocTypesAsCertainTip(); + }; + return [ + $addTip(RuleErrorBuilder::message(sprintf( + 'Casting to %s something that\'s already %s.', + $castType->describe(VerbosityLevel::typeOnly()), + $expressionType->describe(VerbosityLevel::typeOnly()) + )))->identifier('cast.useless')->build(), + ]; + } + + return []; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Classes/RequireParentConstructCallRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Classes/RequireParentConstructCallRule.php new file mode 100644 index 0000000..76d3d16 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Classes/RequireParentConstructCallRule.php @@ -0,0 +1,141 @@ + + */ +class RequireParentConstructCallRule implements Rule +{ + + public function getNodeType(): string + { + return ClassMethod::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if (!$scope->isInClass()) { + throw new ShouldNotHappenException(); + } + + if ($scope->isInTrait()) { + return []; + } + + if ($node->name->name !== '__construct') { + return []; + } + + if ($node->isAbstract()) { + return []; + } + + $classReflection = $scope->getClassReflection()->getNativeReflection(); + if ($classReflection->isInterface() || $classReflection->isAnonymous()) { + return []; + } + + if ($this->callsParentConstruct($node)) { + return []; + } + + $parentClass = $this->getParentConstructorClass($classReflection); + if ($parentClass !== false) { + return [ + RuleErrorBuilder::message(sprintf( + '%s::__construct() does not call parent constructor from %s.', + $classReflection->getName(), + $parentClass->getName() + ))->identifier('constructor.missingParentCall')->build(), + ]; + } + + return []; + } + + private function callsParentConstruct(Node $parserNode): bool + { + if (!property_exists($parserNode, 'stmts')) { + return false; + } + + foreach ($parserNode->stmts as $statement) { + if ($statement instanceof Node\Stmt\Expression) { + $statement = $statement->expr; + } + + $statement = $this->ignoreErrorSuppression($statement); + if ($statement instanceof StaticCall) { + if ( + $statement->class instanceof Name + && ((string) $statement->class === 'parent') + && $statement->name instanceof Node\Identifier + && $statement->name->name === '__construct' + ) { + return true; + } + } else { + if ($this->callsParentConstruct($statement)) { + return true; + } + } + } + + return false; + } + + /** + * @param ReflectionClass|ReflectionEnum $classReflection + * @return ReflectionClass|false + */ + private function getParentConstructorClass($classReflection) + { + while ($classReflection->getParentClass() !== false) { + $constructor = $classReflection->getParentClass()->hasMethod('__construct') ? $classReflection->getParentClass()->getMethod('__construct') : null; + $constructorWithClassName = $classReflection->getParentClass()->hasMethod($classReflection->getParentClass()->getName()) ? $classReflection->getParentClass()->getMethod($classReflection->getParentClass()->getName()) : null; + if ( + ( + $constructor !== null + && $constructor->getDeclaringClass()->getName() === $classReflection->getParentClass()->getName() + && !$constructor->isAbstract() + && !$constructor->isPrivate() + ) || ( + $constructorWithClassName !== null + && $constructorWithClassName->getDeclaringClass()->getName() === $classReflection->getParentClass()->getName() + && !$constructorWithClassName->isAbstract() + ) + ) { + return $classReflection->getParentClass(); + } + + $classReflection = $classReflection->getParentClass(); + } + + return false; + } + + private function ignoreErrorSuppression(Node $statement): Node + { + if ($statement instanceof Node\Expr\ErrorSuppress) { + + return $statement->expr; + } + + return $statement; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/DisallowedConstructs/DisallowedBacktickRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/DisallowedConstructs/DisallowedBacktickRule.php new file mode 100644 index 0000000..76e401c --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/DisallowedConstructs/DisallowedBacktickRule.php @@ -0,0 +1,31 @@ + + */ +class DisallowedBacktickRule implements Rule +{ + + public function getNodeType(): string + { + return ShellExec::class; + } + + public function processNode(Node $node, Scope $scope): array + { + return [ + RuleErrorBuilder::message('Backtick operator is not allowed. Use shell_exec() instead.') + ->identifier('backtick.notAllowed') + ->build(), + ]; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/DisallowedConstructs/DisallowedEmptyRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/DisallowedConstructs/DisallowedEmptyRule.php new file mode 100644 index 0000000..d19f5ea --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/DisallowedConstructs/DisallowedEmptyRule.php @@ -0,0 +1,31 @@ + + */ +class DisallowedEmptyRule implements Rule +{ + + public function getNodeType(): string + { + return Empty_::class; + } + + public function processNode(Node $node, Scope $scope): array + { + return [ + RuleErrorBuilder::message('Construct empty() is not allowed. Use more strict comparison.') + ->identifier('empty.notAllowed') + ->build(), + ]; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/DisallowedConstructs/DisallowedImplicitArrayCreationRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/DisallowedConstructs/DisallowedImplicitArrayCreationRule.php new file mode 100644 index 0000000..cee777c --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/DisallowedConstructs/DisallowedImplicitArrayCreationRule.php @@ -0,0 +1,65 @@ + + */ +class DisallowedImplicitArrayCreationRule implements Rule +{ + + public function getNodeType(): string + { + return Assign::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if (!$node->var instanceof ArrayDimFetch) { + return []; + } + + $node = $node->var; + while ($node instanceof ArrayDimFetch) { + $node = $node->var; + } + + if (!$node instanceof Variable) { + return []; + } + + if (!is_string($node->name)) { + return []; + } + + $certainty = $scope->hasVariableType($node->name); + if ($certainty->no()) { + return [ + RuleErrorBuilder::message(sprintf('Implicit array creation is not allowed - variable $%s does not exist.', $node->name)) + ->identifier('variable.implicitArray') + ->build(), + ]; + } + + if ($certainty->maybe()) { + return [ + RuleErrorBuilder::message(sprintf('Implicit array creation is not allowed - variable $%s might not exist.', $node->name)) + ->identifier('variable.implicitArray') + ->build(), + ]; + } + + return []; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/DisallowedConstructs/DisallowedLooseComparisonRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/DisallowedConstructs/DisallowedLooseComparisonRule.php new file mode 100644 index 0000000..9b709be --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/DisallowedConstructs/DisallowedLooseComparisonRule.php @@ -0,0 +1,48 @@ + + */ +class DisallowedLooseComparisonRule implements Rule +{ + + public function getNodeType(): string + { + return BinaryOp::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if ($node instanceof Equal) { + return [ + RuleErrorBuilder::message( + 'Loose comparison via "==" is not allowed.' + )->tip('Use strict comparison via "===" instead.') + ->identifier('equal.notAllowed') + ->build(), + ]; + } + if ($node instanceof NotEqual) { + return [ + RuleErrorBuilder::message( + 'Loose comparison via "!=" is not allowed.' + )->tip('Use strict comparison via "!==" instead.') + ->identifier('notEqual.notAllowed') + ->build(), + ]; + } + + return []; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/DisallowedConstructs/DisallowedShortTernaryRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/DisallowedConstructs/DisallowedShortTernaryRule.php new file mode 100644 index 0000000..fac4279 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/DisallowedConstructs/DisallowedShortTernaryRule.php @@ -0,0 +1,35 @@ + + */ +class DisallowedShortTernaryRule implements Rule +{ + + public function getNodeType(): string + { + return Ternary::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if ($node->if !== null) { + return []; + } + + return [ + RuleErrorBuilder::message('Short ternary operator is not allowed. Use null coalesce operator if applicable or consider using long ternary.') + ->identifier('ternary.shortNotAllowed') + ->build(), + ]; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/ForLoop/OverwriteVariablesWithForLoopInitRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/ForLoop/OverwriteVariablesWithForLoopInitRule.php new file mode 100644 index 0000000..f710474 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/ForLoop/OverwriteVariablesWithForLoopInitRule.php @@ -0,0 +1,77 @@ + + */ +class OverwriteVariablesWithForLoopInitRule implements Rule +{ + + public function getNodeType(): string + { + return For_::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $errors = []; + foreach ($node->init as $expr) { + if (!($expr instanceof Assign)) { + continue; + } + + foreach ($this->checkValueVar($scope, $expr->var) as $error) { + $errors[] = $error; + } + } + + return $errors; + } + + /** + * @return list + */ + private function checkValueVar(Scope $scope, Expr $expr): array + { + $errors = []; + if ( + $expr instanceof Node\Expr\Variable + && is_string($expr->name) + && $scope->hasVariableType($expr->name)->yes() + ) { + $errors[] = RuleErrorBuilder::message(sprintf('For loop initial assignment overwrites variable $%s.', $expr->name)) + ->identifier('for.variableOverwrite') + ->build(); + } + + if ( + $expr instanceof Node\Expr\List_ + || $expr instanceof Node\Expr\Array_ + ) { + foreach ($expr->items as $item) { + if ($item === null) { + continue; + } + + foreach ($this->checkValueVar($scope, $item->value) as $error) { + $errors[] = $error; + } + } + } + + return $errors; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/ForeachLoop/OverwriteVariablesWithForeachRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/ForeachLoop/OverwriteVariablesWithForeachRule.php new file mode 100644 index 0000000..0cf620c --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/ForeachLoop/OverwriteVariablesWithForeachRule.php @@ -0,0 +1,80 @@ + + */ +class OverwriteVariablesWithForeachRule implements Rule +{ + + public function getNodeType(): string + { + return Foreach_::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $errors = []; + if ( + $node->keyVar instanceof Node\Expr\Variable + && is_string($node->keyVar->name) + && $scope->hasVariableType($node->keyVar->name)->yes() + ) { + $errors[] = RuleErrorBuilder::message(sprintf('Foreach overwrites $%s with its key variable.', $node->keyVar->name)) + ->identifier('foreach.keyOverwrite') + ->build(); + } + + foreach ($this->checkValueVar($scope, $node->valueVar) as $error) { + $errors[] = $error; + } + + return $errors; + } + + /** + * @return list + */ + private function checkValueVar(Scope $scope, Expr $expr): array + { + $errors = []; + if ( + $expr instanceof Node\Expr\Variable + && is_string($expr->name) + && $scope->hasVariableType($expr->name)->yes() + ) { + $errors[] = RuleErrorBuilder::message(sprintf('Foreach overwrites $%s with its value variable.', $expr->name)) + ->identifier('foreach.valueOverwrite') + ->build(); + } + + if ( + $expr instanceof Node\Expr\List_ + || $expr instanceof Node\Expr\Array_ + ) { + foreach ($expr->items as $item) { + if ($item === null) { + continue; + } + + foreach ($this->checkValueVar($scope, $item->value) as $error) { + $errors[] = $error; + } + } + } + + return $errors; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Functions/ArrayFilterStrictRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Functions/ArrayFilterStrictRule.php new file mode 100644 index 0000000..59c0570 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Functions/ArrayFilterStrictRule.php @@ -0,0 +1,166 @@ + + */ +class ArrayFilterStrictRule implements Rule +{ + + /** @var ReflectionProvider */ + private $reflectionProvider; + + /** @var bool */ + private $treatPhpDocTypesAsCertain; + + /** @var bool */ + private $checkNullables; + + /** @var bool */ + private $treatPhpDocTypesAsCertainTip; + + public function __construct( + ReflectionProvider $reflectionProvider, + bool $treatPhpDocTypesAsCertain, + bool $checkNullables, + bool $treatPhpDocTypesAsCertainTip + ) + { + $this->reflectionProvider = $reflectionProvider; + $this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain; + $this->checkNullables = $checkNullables; + $this->treatPhpDocTypesAsCertainTip = $treatPhpDocTypesAsCertainTip; + } + + public function getNodeType(): string + { + return FuncCall::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if (!$node->name instanceof Name) { + return []; + } + + if (!$this->reflectionProvider->hasFunction($node->name, $scope)) { + return []; + } + + $functionReflection = $this->reflectionProvider->getFunction($node->name, $scope); + + if ($functionReflection->getName() !== 'array_filter') { + return []; + } + + $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs( + $scope, + $node->getArgs(), + $functionReflection->getVariants(), + $functionReflection->getNamedArgumentsVariants() + ); + + $normalizedFuncCall = ArgumentsNormalizer::reorderFuncArguments($parametersAcceptor, $node); + + if ($normalizedFuncCall === null) { + return []; + } + + $args = $normalizedFuncCall->getArgs(); + if (count($args) === 0) { + return []; + } + + if (count($args) === 1) { + $arrayType = $scope->getType($args[0]->value); + $itemType = $arrayType->getIterableValueType(); + if ($itemType instanceof UnionType) { + $hasTruthy = false; + $hasFalsey = false; + foreach ($itemType->getTypes() as $innerType) { + $booleanType = $innerType->toBoolean(); + if ($booleanType->isTrue()->yes()) { + $hasTruthy = true; + continue; + } + if ($booleanType->isFalse()->yes()) { + $hasFalsey = true; + continue; + } + + $hasTruthy = false; + $hasFalsey = false; + break; + } + + if ($hasTruthy && $hasFalsey) { + return []; + } + } elseif ($itemType->isBoolean()->yes()) { + return []; + } elseif ($itemType->isArray()->yes()) { + return []; + } + + return [ + RuleErrorBuilder::message('Call to function array_filter() requires parameter #2 to be passed to avoid loose comparison semantics.') + ->identifier('arrayFilter.strict') + ->build(), + ]; + } + + $nativeCallbackType = $scope->getNativeType($args[1]->value); + + if ($this->treatPhpDocTypesAsCertain) { + $callbackType = $scope->getType($args[1]->value); + } else { + $callbackType = $nativeCallbackType; + } + + if ($this->isCallbackTypeNull($callbackType)) { + $message = 'Parameter #2 of array_filter() cannot be null to avoid loose comparison semantics (%s given).'; + $errorBuilder = RuleErrorBuilder::message(sprintf( + $message, + $callbackType->describe(VerbosityLevel::typeOnly()) + ))->identifier('arrayFilter.strict'); + + if ($this->treatPhpDocTypesAsCertainTip && !$this->isCallbackTypeNull($nativeCallbackType) && $this->treatPhpDocTypesAsCertain) { + $errorBuilder->treatPhpDocTypesAsCertainTip(); + } + + return [$errorBuilder->build()]; + } + + return []; + } + + private function isCallbackTypeNull(Type $callbackType): bool + { + if ($callbackType->isNull()->yes()) { + return true; + } + + if ($callbackType->isNull()->no()) { + return false; + } + + return $this->checkNullables; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Functions/ClosureUsesThisRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Functions/ClosureUsesThisRule.php new file mode 100644 index 0000000..d2cb4a4 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Functions/ClosureUsesThisRule.php @@ -0,0 +1,52 @@ + + */ +class ClosureUsesThisRule implements Rule +{ + + public function getNodeType(): string + { + return Node\Expr\Closure::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if ($node->static) { + return []; + } + + if ($scope->isInClosureBind()) { + return []; + } + + $messages = []; + foreach ($node->uses as $closureUse) { + $varType = $scope->getType($closureUse->var); + if (!is_string($closureUse->var->name)) { + continue; + } + if (!$varType instanceof ThisType) { + continue; + } + + $messages[] = RuleErrorBuilder::message(sprintf('Anonymous function uses $this assigned to variable $%s. Use $this directly in the function body.', $closureUse->var->name)) + ->line($closureUse->getLine()) + ->identifier('closure.useThis') + ->build(); + } + return $messages; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Methods/WrongCaseOfInheritedMethodRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Methods/WrongCaseOfInheritedMethodRule.php new file mode 100644 index 0000000..1cca26e --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Methods/WrongCaseOfInheritedMethodRule.php @@ -0,0 +1,86 @@ + + */ +class WrongCaseOfInheritedMethodRule implements Rule +{ + + public function getNodeType(): string + { + return InClassMethodNode::class; + } + + public function processNode( + Node $node, + Scope $scope + ): array + { + $methodReflection = $node->getMethodReflection(); + $declaringClass = $methodReflection->getDeclaringClass(); + + $messages = []; + if ($declaringClass->getParentClass() !== null) { + $parentMessage = $this->findMethod( + $declaringClass, + $declaringClass->getParentClass(), + $methodReflection->getName() + ); + if ($parentMessage !== null) { + $messages[] = $parentMessage; + } + } + + foreach ($declaringClass->getInterfaces() as $interface) { + $interfaceMessage = $this->findMethod( + $declaringClass, + $interface, + $methodReflection->getName() + ); + if ($interfaceMessage === null) { + continue; + } + + $messages[] = $interfaceMessage; + } + + return $messages; + } + + private function findMethod( + ClassReflection $declaringClass, + ClassReflection $classReflection, + string $methodName + ): ?IdentifierRuleError + { + if (!$classReflection->hasNativeMethod($methodName)) { + return null; + } + + $parentMethod = $classReflection->getNativeMethod($methodName); + if ($parentMethod->getName() === $methodName) { + return null; + } + + return RuleErrorBuilder::message(sprintf( + 'Method %s::%s() does not match %s method name: %s::%s().', + $declaringClass->getDisplayName(), + $methodName, + $classReflection->isInterface() ? 'interface' : 'parent', + $classReflection->getDisplayName(), + $parentMethod->getName() + ))->identifier('method.nameCase')->build(); + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandInArithmeticIncrementOrDecrementRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandInArithmeticIncrementOrDecrementRule.php new file mode 100644 index 0000000..af82a08 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandInArithmeticIncrementOrDecrementRule.php @@ -0,0 +1,62 @@ + + */ +abstract class OperandInArithmeticIncrementOrDecrementRule implements Rule +{ + + /** @var OperatorRuleHelper */ + private $helper; + + public function __construct(OperatorRuleHelper $helper) + { + $this->helper = $helper; + } + + /** + * @param TNodeType $node + */ + public function processNode(Node $node, Scope $scope): array + { + $messages = []; + $varType = $scope->getType($node->var); + + if ( + ($node instanceof PreInc || $node instanceof PostInc) + && !$this->helper->isValidForIncrement($scope, $node->var) + || ($node instanceof PreDec || $node instanceof PostDec) + && !$this->helper->isValidForDecrement($scope, $node->var) + ) { + $messages[] = RuleErrorBuilder::message(sprintf( + 'Only numeric types are allowed in %s, %s given.', + $this->describeOperation(), + $varType->describe(VerbosityLevel::typeOnly()) + ))->identifier(sprintf('%s.nonNumeric', $this->getIdentifier()))->build(); + } + + return $messages; + } + + abstract protected function describeOperation(): string; + + /** + * @return 'preInc'|'postInc'|'preDec'|'postDec' + */ + abstract protected function getIdentifier(): string; + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandInArithmeticPostDecrementRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandInArithmeticPostDecrementRule.php new file mode 100644 index 0000000..d0e0809 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandInArithmeticPostDecrementRule.php @@ -0,0 +1,28 @@ + + */ +class OperandInArithmeticPostDecrementRule extends OperandInArithmeticIncrementOrDecrementRule +{ + + public function getNodeType(): string + { + return PostDec::class; + } + + protected function describeOperation(): string + { + return 'post-decrement'; + } + + protected function getIdentifier(): string + { + return 'postDec'; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandInArithmeticPostIncrementRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandInArithmeticPostIncrementRule.php new file mode 100644 index 0000000..400d828 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandInArithmeticPostIncrementRule.php @@ -0,0 +1,28 @@ + + */ +class OperandInArithmeticPostIncrementRule extends OperandInArithmeticIncrementOrDecrementRule +{ + + public function getNodeType(): string + { + return PostInc::class; + } + + protected function describeOperation(): string + { + return 'post-increment'; + } + + protected function getIdentifier(): string + { + return 'postInc'; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandInArithmeticPreDecrementRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandInArithmeticPreDecrementRule.php new file mode 100644 index 0000000..9d58356 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandInArithmeticPreDecrementRule.php @@ -0,0 +1,28 @@ + + */ +class OperandInArithmeticPreDecrementRule extends OperandInArithmeticIncrementOrDecrementRule +{ + + public function getNodeType(): string + { + return PreDec::class; + } + + protected function describeOperation(): string + { + return 'pre-decrement'; + } + + protected function getIdentifier(): string + { + return 'preDec'; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandInArithmeticPreIncrementRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandInArithmeticPreIncrementRule.php new file mode 100644 index 0000000..d5d81f2 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandInArithmeticPreIncrementRule.php @@ -0,0 +1,28 @@ + + */ +class OperandInArithmeticPreIncrementRule extends OperandInArithmeticIncrementOrDecrementRule +{ + + public function getNodeType(): string + { + return PreInc::class; + } + + protected function describeOperation(): string + { + return 'pre-increment'; + } + + protected function getIdentifier(): string + { + return 'preInc'; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandsInArithmeticAdditionRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandsInArithmeticAdditionRule.php new file mode 100644 index 0000000..246b609 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandsInArithmeticAdditionRule.php @@ -0,0 +1,74 @@ + + */ +class OperandsInArithmeticAdditionRule implements Rule +{ + + /** @var OperatorRuleHelper */ + private $helper; + + /** @var bool */ + private $bleedingEdge; + + public function __construct(OperatorRuleHelper $helper, bool $bleedingEdge) + { + $this->helper = $helper; + $this->bleedingEdge = $bleedingEdge; + } + + public function getNodeType(): string + { + return Expr::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if ($node instanceof BinaryOpPlus) { + $left = $node->left; + $right = $node->right; + } elseif ($node instanceof AssignOpPlus && $this->bleedingEdge) { + $left = $node->var; + $right = $node->expr; + } else { + return []; + } + + $leftType = $scope->getType($left); + $rightType = $scope->getType($right); + if (count($leftType->getArrays()) > 0 && count($rightType->getArrays()) > 0) { + return []; + } + + $messages = []; + if (!$this->helper->isValidForArithmeticOperation($scope, $left)) { + $messages[] = RuleErrorBuilder::message(sprintf( + 'Only numeric types are allowed in +, %s given on the left side.', + $leftType->describe(VerbosityLevel::typeOnly()) + ))->identifier('plus.leftNonNumeric')->build(); + } + if (!$this->helper->isValidForArithmeticOperation($scope, $right)) { + $messages[] = RuleErrorBuilder::message(sprintf( + 'Only numeric types are allowed in +, %s given on the right side.', + $rightType->describe(VerbosityLevel::typeOnly()) + ))->identifier('plus.rightNonNumeric')->build(); + } + + return $messages; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandsInArithmeticDivisionRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandsInArithmeticDivisionRule.php new file mode 100644 index 0000000..8a146de --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandsInArithmeticDivisionRule.php @@ -0,0 +1,70 @@ + + */ +class OperandsInArithmeticDivisionRule implements Rule +{ + + /** @var OperatorRuleHelper */ + private $helper; + + /** @var bool */ + private $bleedingEdge; + + public function __construct(OperatorRuleHelper $helper, bool $bleedingEdge) + { + $this->helper = $helper; + $this->bleedingEdge = $bleedingEdge; + } + + public function getNodeType(): string + { + return Expr::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if ($node instanceof BinaryOpDiv) { + $left = $node->left; + $right = $node->right; + } elseif ($node instanceof AssignOpDiv && $this->bleedingEdge) { + $left = $node->var; + $right = $node->expr; + } else { + return []; + } + + $messages = []; + $leftType = $scope->getType($left); + if (!$this->helper->isValidForArithmeticOperation($scope, $left)) { + $messages[] = RuleErrorBuilder::message(sprintf( + 'Only numeric types are allowed in /, %s given on the left side.', + $leftType->describe(VerbosityLevel::typeOnly()) + ))->identifier('div.leftNonNumeric')->build(); + } + + $rightType = $scope->getType($right); + if (!$this->helper->isValidForArithmeticOperation($scope, $right)) { + $messages[] = RuleErrorBuilder::message(sprintf( + 'Only numeric types are allowed in /, %s given on the right side.', + $rightType->describe(VerbosityLevel::typeOnly()) + ))->identifier('div.rightNonNumeric')->build(); + } + + return $messages; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandsInArithmeticExponentiationRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandsInArithmeticExponentiationRule.php new file mode 100644 index 0000000..fe809ef --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandsInArithmeticExponentiationRule.php @@ -0,0 +1,70 @@ + + */ +class OperandsInArithmeticExponentiationRule implements Rule +{ + + /** @var OperatorRuleHelper */ + private $helper; + + /** @var bool */ + private $bleedingEdge; + + public function __construct(OperatorRuleHelper $helper, bool $bleedingEdge) + { + $this->helper = $helper; + $this->bleedingEdge = $bleedingEdge; + } + + public function getNodeType(): string + { + return Expr::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if ($node instanceof BinaryOpPow) { + $left = $node->left; + $right = $node->right; + } elseif ($node instanceof AssignOpPow && $this->bleedingEdge) { + $left = $node->var; + $right = $node->expr; + } else { + return []; + } + + $messages = []; + $leftType = $scope->getType($left); + if (!$this->helper->isValidForArithmeticOperation($scope, $left)) { + $messages[] = RuleErrorBuilder::message(sprintf( + 'Only numeric types are allowed in **, %s given on the left side.', + $leftType->describe(VerbosityLevel::typeOnly()) + ))->identifier('pow.leftNonNumeric')->build(); + } + + $rightType = $scope->getType($right); + if (!$this->helper->isValidForArithmeticOperation($scope, $right)) { + $messages[] = RuleErrorBuilder::message(sprintf( + 'Only numeric types are allowed in **, %s given on the right side.', + $rightType->describe(VerbosityLevel::typeOnly()) + ))->identifier('pow.rightNonNumeric')->build(); + } + + return $messages; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandsInArithmeticModuloRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandsInArithmeticModuloRule.php new file mode 100644 index 0000000..4aad366 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandsInArithmeticModuloRule.php @@ -0,0 +1,70 @@ + + */ +class OperandsInArithmeticModuloRule implements Rule +{ + + /** @var OperatorRuleHelper */ + private $helper; + + /** @var bool */ + private $bleedingEdge; + + public function __construct(OperatorRuleHelper $helper, bool $bleedingEdge) + { + $this->helper = $helper; + $this->bleedingEdge = $bleedingEdge; + } + + public function getNodeType(): string + { + return Expr::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if ($node instanceof BinaryOpMod) { + $left = $node->left; + $right = $node->right; + } elseif ($node instanceof AssignOpMod && $this->bleedingEdge) { + $left = $node->var; + $right = $node->expr; + } else { + return []; + } + + $messages = []; + $leftType = $scope->getType($left); + if (!$this->helper->isValidForArithmeticOperation($scope, $left)) { + $messages[] = RuleErrorBuilder::message(sprintf( + 'Only numeric types are allowed in %%, %s given on the left side.', + $leftType->describe(VerbosityLevel::typeOnly()) + ))->identifier('mod.leftNonNumeric')->build(); + } + + $rightType = $scope->getType($right); + if (!$this->helper->isValidForArithmeticOperation($scope, $right)) { + $messages[] = RuleErrorBuilder::message(sprintf( + 'Only numeric types are allowed in %%, %s given on the right side.', + $rightType->describe(VerbosityLevel::typeOnly()) + ))->identifier('mod.rightNonNumeric')->build(); + } + + return $messages; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandsInArithmeticMultiplicationRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandsInArithmeticMultiplicationRule.php new file mode 100644 index 0000000..f662bdc --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandsInArithmeticMultiplicationRule.php @@ -0,0 +1,70 @@ + + */ +class OperandsInArithmeticMultiplicationRule implements Rule +{ + + /** @var OperatorRuleHelper */ + private $helper; + + /** @var bool */ + private $bleedingEdge; + + public function __construct(OperatorRuleHelper $helper, bool $bleedingEdge) + { + $this->helper = $helper; + $this->bleedingEdge = $bleedingEdge; + } + + public function getNodeType(): string + { + return Expr::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if ($node instanceof BinaryOpMul) { + $left = $node->left; + $right = $node->right; + } elseif ($node instanceof AssignOpMul && $this->bleedingEdge) { + $left = $node->var; + $right = $node->expr; + } else { + return []; + } + + $messages = []; + $leftType = $scope->getType($left); + if (!$this->helper->isValidForArithmeticOperation($scope, $left)) { + $messages[] = RuleErrorBuilder::message(sprintf( + 'Only numeric types are allowed in *, %s given on the left side.', + $leftType->describe(VerbosityLevel::typeOnly()) + ))->identifier('mul.leftNonNumeric')->build(); + } + + $rightType = $scope->getType($right); + if (!$this->helper->isValidForArithmeticOperation($scope, $right)) { + $messages[] = RuleErrorBuilder::message(sprintf( + 'Only numeric types are allowed in *, %s given on the right side.', + $rightType->describe(VerbosityLevel::typeOnly()) + ))->identifier('mul.rightNonNumeric')->build(); + } + + return $messages; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandsInArithmeticSubtractionRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandsInArithmeticSubtractionRule.php new file mode 100644 index 0000000..9bec287 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperandsInArithmeticSubtractionRule.php @@ -0,0 +1,70 @@ + + */ +class OperandsInArithmeticSubtractionRule implements Rule +{ + + /** @var OperatorRuleHelper */ + private $helper; + + /** @var bool */ + private $bleedingEdge; + + public function __construct(OperatorRuleHelper $helper, bool $bleedingEdge) + { + $this->helper = $helper; + $this->bleedingEdge = $bleedingEdge; + } + + public function getNodeType(): string + { + return Expr::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if ($node instanceof BinaryOpMinus) { + $left = $node->left; + $right = $node->right; + } elseif ($node instanceof AssignOpMinus && $this->bleedingEdge) { + $left = $node->var; + $right = $node->expr; + } else { + return []; + } + + $messages = []; + $leftType = $scope->getType($left); + if (!$this->helper->isValidForArithmeticOperation($scope, $left)) { + $messages[] = RuleErrorBuilder::message(sprintf( + 'Only numeric types are allowed in -, %s given on the left side.', + $leftType->describe(VerbosityLevel::typeOnly()) + ))->identifier('minus.leftNonNumeric')->build(); + } + + $rightType = $scope->getType($right); + if (!$this->helper->isValidForArithmeticOperation($scope, $right)) { + $messages[] = RuleErrorBuilder::message(sprintf( + 'Only numeric types are allowed in -, %s given on the right side.', + $rightType->describe(VerbosityLevel::typeOnly()) + ))->identifier('minus.rightNonNumeric')->build(); + } + + return $messages; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperatorRuleHelper.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperatorRuleHelper.php new file mode 100644 index 0000000..2890285 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/Operators/OperatorRuleHelper.php @@ -0,0 +1,95 @@ +ruleLevelHelper = $ruleLevelHelper; + } + + public function isValidForArithmeticOperation(Scope $scope, Expr $expr): bool + { + $type = $scope->getType($expr); + if ($type instanceof MixedType) { + return true; + } + + // already reported by PHPStan core + if ($type->toNumber() instanceof ErrorType) { + return true; + } + + return $this->isSubtypeOfNumber($scope, $expr); + } + + public function isValidForIncrement(Scope $scope, Expr $expr): bool + { + $type = $scope->getType($expr); + if ($type instanceof MixedType) { + return true; + } + + if ($type->isString()->yes()) { + // Because `$a = 'a'; $a++;` is valid + return true; + } + + return $this->isSubtypeOfNumber($scope, $expr); + } + + public function isValidForDecrement(Scope $scope, Expr $expr): bool + { + $type = $scope->getType($expr); + if ($type instanceof MixedType) { + return true; + } + + return $this->isSubtypeOfNumber($scope, $expr); + } + + private function isSubtypeOfNumber(Scope $scope, Expr $expr): bool + { + $acceptedType = new UnionType([new IntegerType(), new FloatType(), new IntersectionType([new StringType(), new AccessoryNumericStringType()])]); + + $type = $this->ruleLevelHelper->findTypeToCheck( + $scope, + $expr, + '', + static function (Type $type) use ($acceptedType): bool { + return $acceptedType->isSuperTypeOf($type)->yes(); + } + )->getType(); + + if ($type instanceof ErrorType) { + return true; + } + + $isSuperType = $acceptedType->isSuperTypeOf($type); + if ($type instanceof BenevolentUnionType) { + return !$isSuperType->no(); + } + + return $isSuperType->yes(); + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/StrictCalls/DynamicCallOnStaticMethodsCallableRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/StrictCalls/DynamicCallOnStaticMethodsCallableRule.php new file mode 100644 index 0000000..d14b567 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/StrictCalls/DynamicCallOnStaticMethodsCallableRule.php @@ -0,0 +1,68 @@ + + */ +class DynamicCallOnStaticMethodsCallableRule implements Rule +{ + + /** @var RuleLevelHelper */ + private $ruleLevelHelper; + + public function __construct(RuleLevelHelper $ruleLevelHelper) + { + $this->ruleLevelHelper = $ruleLevelHelper; + } + + public function getNodeType(): string + { + return MethodCallableNode::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if (!$node->getName() instanceof Node\Identifier) { + return []; + } + + $name = $node->getName()->name; + $type = $this->ruleLevelHelper->findTypeToCheck( + $scope, + $node->getVar(), + '', + static function (Type $type) use ($name): bool { + return $type->canCallMethods()->yes() && $type->hasMethod($name)->yes(); + } + )->getType(); + + if ($type instanceof ErrorType || !$type->canCallMethods()->yes() || !$type->hasMethod($name)->yes()) { + return []; + } + + $methodReflection = $type->getMethod($name, $scope); + if ($methodReflection->isStatic()) { + return [ + RuleErrorBuilder::message(sprintf( + 'Dynamic call to static method %s::%s().', + $methodReflection->getDeclaringClass()->getDisplayName(), + $methodReflection->getName() + ))->identifier('staticMethod.dynamicCall')->build(), + ]; + } + + return []; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/StrictCalls/DynamicCallOnStaticMethodsRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/StrictCalls/DynamicCallOnStaticMethodsRule.php new file mode 100644 index 0000000..44b180c --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/StrictCalls/DynamicCallOnStaticMethodsRule.php @@ -0,0 +1,79 @@ + + */ +class DynamicCallOnStaticMethodsRule implements Rule +{ + + /** @var RuleLevelHelper */ + private $ruleLevelHelper; + + public function __construct(RuleLevelHelper $ruleLevelHelper) + { + $this->ruleLevelHelper = $ruleLevelHelper; + } + + public function getNodeType(): string + { + return MethodCall::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if (!$node->name instanceof Node\Identifier) { + return []; + } + + $name = $node->name->name; + $type = $this->ruleLevelHelper->findTypeToCheck( + $scope, + $node->var, + '', + static function (Type $type) use ($name): bool { + return $type->canCallMethods()->yes() && $type->hasMethod($name)->yes(); + } + )->getType(); + + if ($type instanceof ErrorType || !$type->canCallMethods()->yes() || !$type->hasMethod($name)->yes()) { + return []; + } + + $methodReflection = $type->getMethod($name, $scope); + if ($methodReflection->isStatic()) { + $prototype = $methodReflection->getPrototype(); + if (in_array($prototype->getDeclaringClass()->getName(), [ + TypeInferenceTestCase::class, + PHPStanTestCase::class, + ], true)) { + return []; + } + + return [ + RuleErrorBuilder::message(sprintf( + 'Dynamic call to static method %s::%s().', + $methodReflection->getDeclaringClass()->getDisplayName(), + $methodReflection->getName() + ))->identifier('staticMethod.dynamicCall')->build(), + ]; + } + + return []; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/StrictCalls/StrictFunctionCallsRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/StrictCalls/StrictFunctionCallsRule.php new file mode 100644 index 0000000..2ae134b --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/StrictCalls/StrictFunctionCallsRule.php @@ -0,0 +1,97 @@ + + */ +class StrictFunctionCallsRule implements Rule +{ + + /** @var int[] */ + private $functionArguments = [ + 'in_array' => 2, + 'array_search' => 2, + 'base64_decode' => 1, + 'array_keys' => 2, + ]; + + /** @var ReflectionProvider */ + private $reflectionProvider; + + public function __construct(ReflectionProvider $reflectionProvider) + { + $this->reflectionProvider = $reflectionProvider; + } + + public function getNodeType(): string + { + return FuncCall::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if (!$node->name instanceof Name) { + return []; + } + + if (!$this->reflectionProvider->hasFunction($node->name, $scope)) { + return []; + } + + $function = $this->reflectionProvider->getFunction($node->name, $scope); + $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $node->getArgs(), $function->getVariants()); + $node = ArgumentsNormalizer::reorderFuncArguments($parametersAcceptor, $node); + if ($node === null) { + return []; + } + $functionName = strtolower($function->getName()); + if (!array_key_exists($functionName, $this->functionArguments)) { + return []; + } + + if ($functionName === 'array_keys' && !array_key_exists(1, $node->getArgs())) { + return []; + } + + $argumentPosition = $this->functionArguments[$functionName]; + if (!array_key_exists($argumentPosition, $node->getArgs())) { + return [ + RuleErrorBuilder::message(sprintf( + 'Call to function %s() requires parameter #%d to be set.', + $functionName, + $argumentPosition + 1 + ))->identifier('function.strict')->build(), + ]; + } + + $argumentType = $scope->getType($node->getArgs()[$argumentPosition]->value); + $trueType = new ConstantBooleanType(true); + if (!$trueType->isSuperTypeOf($argumentType)->yes()) { + return [ + RuleErrorBuilder::message(sprintf( + 'Call to function %s() requires parameter #%d to be true.', + $functionName, + $argumentPosition + 1 + ))->identifier('function.strict')->build(), + ]; + } + + return []; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/SwitchConditions/MatchingTypeInSwitchCaseConditionRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/SwitchConditions/MatchingTypeInSwitchCaseConditionRule.php new file mode 100644 index 0000000..e52195a --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/SwitchConditions/MatchingTypeInSwitchCaseConditionRule.php @@ -0,0 +1,61 @@ + + */ +class MatchingTypeInSwitchCaseConditionRule implements Rule +{ + + /** @var Standard */ + private $printer; + + public function __construct(Standard $printer) + { + $this->printer = $printer; + } + + public function getNodeType(): string + { + return Switch_::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $messages = []; + $conditionType = $scope->getType($node->cond); + foreach ($node->cases as $case) { + if ($case->cond === null) { + continue; + } + + $caseType = $scope->getType($case->cond); + if (!$conditionType->isSuperTypeOf($caseType)->no()) { + continue; + } + + $messages[] = RuleErrorBuilder::message(sprintf( + 'Switch condition type (%s) does not match case condition %s (%s).', + $conditionType->describe(VerbosityLevel::value()), + $this->printer->prettyPrintExpr($case->cond), + $caseType->describe(VerbosityLevel::typeOnly()) + )) + ->line($case->getLine()) + ->identifier('switch.type') + ->build(); + } + + return $messages; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariableMethodCallRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariableMethodCallRule.php new file mode 100644 index 0000000..f92f84c --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariableMethodCallRule.php @@ -0,0 +1,38 @@ + + */ +class VariableMethodCallRule implements Rule +{ + + public function getNodeType(): string + { + return MethodCall::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if ($node->name instanceof Node\Identifier) { + return []; + } + + return [ + RuleErrorBuilder::message(sprintf( + 'Variable method call on %s.', + $scope->getType($node->var)->describe(VerbosityLevel::typeOnly()) + ))->identifier('method.dynamicName')->build(), + ]; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariableMethodCallableRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariableMethodCallableRule.php new file mode 100644 index 0000000..6a5fd51 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariableMethodCallableRule.php @@ -0,0 +1,38 @@ + + */ +class VariableMethodCallableRule implements Rule +{ + + public function getNodeType(): string + { + return MethodCallableNode::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if ($node->getName() instanceof Node\Identifier) { + return []; + } + + return [ + RuleErrorBuilder::message(sprintf( + 'Variable method call on %s.', + $scope->getType($node->getVar())->describe(VerbosityLevel::typeOnly()) + ))->identifier('method.dynamicName')->build(), + ]; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariablePropertyFetchRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariablePropertyFetchRule.php new file mode 100644 index 0000000..73ff088 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariablePropertyFetchRule.php @@ -0,0 +1,86 @@ + + */ +class VariablePropertyFetchRule implements Rule +{ + + /** @var ReflectionProvider */ + private $reflectionProvider; + + /** @var string[] */ + private $universalObjectCratesClasses; + + /** + * @param string[] $universalObjectCratesClasses + */ + public function __construct(ReflectionProvider $reflectionProvider, array $universalObjectCratesClasses) + { + $this->reflectionProvider = $reflectionProvider; + $this->universalObjectCratesClasses = $universalObjectCratesClasses; + } + + public function getNodeType(): string + { + return PropertyFetch::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if ($node->name instanceof Node\Identifier) { + return []; + } + + $fetchedOnType = $scope->getType($node->var); + foreach ($fetchedOnType->getObjectClassNames() as $referencedClass) { + if (!$this->reflectionProvider->hasClass($referencedClass)) { + continue; + } + + if ($this->isUniversalObjectCrate($this->reflectionProvider->getClass($referencedClass))) { + return []; + } + } + + return [ + RuleErrorBuilder::message(sprintf( + 'Variable property access on %s.', + $fetchedOnType->describe(VerbosityLevel::typeOnly()) + ))->identifier('property.dynamicName')->build(), + ]; + } + + private function isUniversalObjectCrate( + ClassReflection $classReflection + ): bool + { + foreach ($this->universalObjectCratesClasses as $className) { + if (!$this->reflectionProvider->hasClass($className)) { + continue; + } + + if ( + $classReflection->getName() === $className + || $classReflection->isSubclassOf($className) + ) { + return true; + } + } + + return false; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariableStaticMethodCallRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariableStaticMethodCallRule.php new file mode 100644 index 0000000..eb3a770 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariableStaticMethodCallRule.php @@ -0,0 +1,44 @@ + + */ +class VariableStaticMethodCallRule implements Rule +{ + + public function getNodeType(): string + { + return StaticCall::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if ($node->name instanceof Node\Identifier) { + return []; + } + + if ($node->class instanceof Node\Name) { + $methodCalledOn = $scope->resolveName($node->class); + } else { + $methodCalledOn = $scope->getType($node->class)->describe(VerbosityLevel::typeOnly()); + } + + return [ + RuleErrorBuilder::message(sprintf( + 'Variable static method call on %s.', + $methodCalledOn + ))->identifier('staticMethod.dynamicName')->build(), + ]; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariableStaticMethodCallableRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariableStaticMethodCallableRule.php new file mode 100644 index 0000000..f765da6 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariableStaticMethodCallableRule.php @@ -0,0 +1,44 @@ + + */ +class VariableStaticMethodCallableRule implements Rule +{ + + public function getNodeType(): string + { + return StaticMethodCallableNode::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if ($node->getName() instanceof Node\Identifier) { + return []; + } + + if ($node->getClass() instanceof Node\Name) { + $methodCalledOn = $scope->resolveName($node->getClass()); + } else { + $methodCalledOn = $scope->getType($node->getClass())->describe(VerbosityLevel::typeOnly()); + } + + return [ + RuleErrorBuilder::message(sprintf( + 'Variable static method call on %s.', + $methodCalledOn + ))->identifier('staticMethod.dynamicName')->build(), + ]; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariableStaticPropertyFetchRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariableStaticPropertyFetchRule.php new file mode 100644 index 0000000..f27c779 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariableStaticPropertyFetchRule.php @@ -0,0 +1,44 @@ + + */ +class VariableStaticPropertyFetchRule implements Rule +{ + + public function getNodeType(): string + { + return StaticPropertyFetch::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if ($node->name instanceof Node\Identifier) { + return []; + } + + if ($node->class instanceof Node\Name) { + $propertyAccessedOn = $scope->resolveName($node->class); + } else { + $propertyAccessedOn = $scope->getType($node->class)->describe(VerbosityLevel::typeOnly()); + } + + return [ + RuleErrorBuilder::message(sprintf( + 'Variable static property access on %s.', + $propertyAccessedOn + ))->identifier('staticProperty.dynamicName')->build(), + ]; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariableVariablesRule.php b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariableVariablesRule.php new file mode 100644 index 0000000..f78e4ef --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan-strict-rules/src/Rules/VariableVariables/VariableVariablesRule.php @@ -0,0 +1,36 @@ + + */ +class VariableVariablesRule implements Rule +{ + + public function getNodeType(): string + { + return Variable::class; + } + + public function processNode(Node $node, Scope $scope): array + { + if (is_string($node->name)) { + return []; + } + + return [ + RuleErrorBuilder::message('Variable variables are not allowed.') + ->identifier('variable.dynamicName') + ->build(), + ]; + } + +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan/LICENSE b/new/apps/web/src/php/vendor/phpstan/phpstan/LICENSE new file mode 100644 index 0000000..7c0f2b7 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Ondřej Mirtes + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan/README.md b/new/apps/web/src/php/vendor/phpstan/phpstan/README.md new file mode 100644 index 0000000..e3bb940 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan/README.md @@ -0,0 +1,108 @@ +

PHPStan - PHP Static Analysis Tool

+ +

+ PHPStan +

+ +

+ Build Status + Latest Stable Version + Total Downloads + License + PHPStan Enabled +

+ +------ + +PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs +even before you write tests for the code. It moves PHP closer to compiled languages in the sense that the correctness of each line of the code +can be checked before you run the actual line. + +**[Read more about PHPStan »](https://phpstan.org/)** + +**[Try out PHPStan on the on-line playground! »](https://phpstan.org/try)** + +## Sponsors + +TheCodingMachine +    +Private Packagist +
+CDN77 +    +Blackfire.io +
+iO +    +Fame Helsinki +
+ShipMonk +    +Togetter +
+RightCapital +    +ContentKing +
+ZOL +    +EdgeNext +
+Shopware +    +Craft CMS +
+Worksome +    +campoint AG +
+Crisp.nl +    +Inviqa +
+GetResponse +    +Shoptet +
+Route4Me: Route Optimizer and Route Planner Software +    +TicketSwap + + +[**You can now sponsor my open-source work on PHPStan through GitHub Sponsors.**](https://github.com/sponsors/ondrejmirtes) + +Does GitHub already have your 💳? Do you use PHPStan to find 🐛 before they reach production? [Send a couple of 💸 a month my way too.](https://github.com/sponsors/ondrejmirtes) Thank you! + +One-time donations [through Revolut.me](https://revolut.me/ondrejmirtes) are also accepted. To request an invoice, [contact me](mailto:ondrej@mirtes.cz) through e-mail. + +## Documentation + +All the documentation lives on the [phpstan.org website](https://phpstan.org/): + +* [Getting Started & User Guide](https://phpstan.org/user-guide/getting-started) +* [Config Reference](https://phpstan.org/config-reference) +* [PHPDocs Basics](https://phpstan.org/writing-php-code/phpdocs-basics) & [PHPDoc Types](https://phpstan.org/writing-php-code/phpdoc-types) +* [Extension Library](https://phpstan.org/user-guide/extension-library) +* [Developing Extensions](https://phpstan.org/developing-extensions/extension-types) +* [API Reference](https://apiref.phpstan.org/) + +## PHPStan Pro + +PHPStan Pro is a paid add-on on top of open-source PHPStan Static Analysis Tool with these premium features: + +* Web UI for browsing found errors, you can click and open your editor of choice on the offending line. +* Continuous analysis (watch mode): scans changed files in the background, refreshes the UI automatically. + +Try it on PHPStan 0.12.45 or later by running it with the `--pro` option. You can create an account either by following the on-screen instructions, or by visiting [account.phpstan.com](https://account.phpstan.com/). + +After 30-day free trial period it costs 7 EUR for individuals monthly, 70 EUR for teams (up to 25 members). By paying for PHPStan Pro, you're supporting the development of open-source PHPStan. + +You can read more about it on [PHPStan's website](https://phpstan.org/blog/introducing-phpstan-pro). + +## Code of Conduct + +This project adheres to a [Contributor Code of Conduct](https://github.com/phpstan/phpstan/blob/master/CODE_OF_CONDUCT.md). By participating in this project and its community, you are expected to uphold this code. + +## Contributing + +Any contributions are welcome. PHPStan's source code open to pull requests lives at [`phpstan/phpstan-src`](https://github.com/phpstan/phpstan-src). diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan/bootstrap.php b/new/apps/web/src/php/vendor/phpstan/phpstan/bootstrap.php new file mode 100644 index 0000000..2d950b0 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan/bootstrap.php @@ -0,0 +1,135 @@ +loadClass($class); + + return; + } + if (strpos($class, 'PHPStan\\') !== 0 || strpos($class, 'PHPStan\\PhpDocParser\\') === 0) { + return; + } + + if (!in_array('phar', stream_get_wrappers(), true)) { + throw new \Exception('Phar wrapper is not registered. Please review your php.ini settings.'); + } + + if (!self::$polyfillsLoaded) { + self::$polyfillsLoaded = true; + + if ( + PHP_VERSION_ID < 80000 + && empty($GLOBALS['__composer_autoload_files']['a4a119a56e50fbb293281d9a48007e0e']) + && !class_exists(\Symfony\Polyfill\Php80\Php80::class, false) + ) { + $GLOBALS['__composer_autoload_files']['a4a119a56e50fbb293281d9a48007e0e'] = true; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php80/Php80.php'; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php80/bootstrap.php'; + } + + if ( + empty($GLOBALS['__composer_autoload_files']['0e6d7bf4a5811bfa5cf40c5ccd6fae6a']) + && !class_exists(\Symfony\Polyfill\Mbstring\Mbstring::class, false) + ) { + $GLOBALS['__composer_autoload_files']['0e6d7bf4a5811bfa5cf40c5ccd6fae6a'] = true; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-mbstring/Mbstring.php'; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-mbstring/bootstrap.php'; + } + + if ( + empty($GLOBALS['__composer_autoload_files']['e69f7f6ee287b969198c3c9d6777bd38']) + && !class_exists(\Symfony\Polyfill\Intl\Normalizer\Normalizer::class, false) + ) { + $GLOBALS['__composer_autoload_files']['e69f7f6ee287b969198c3c9d6777bd38'] = true; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-intl-normalizer/Normalizer.php'; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-intl-normalizer/bootstrap.php'; + } + + if ( + PHP_VERSION_ID < 70300 + && empty($GLOBALS['__composer_autoload_files']['0d59ee240a4cd96ddbb4ff164fccea4d']) + && !class_exists(\Symfony\Polyfill\Php73\Php73::class, false) + ) { + $GLOBALS['__composer_autoload_files']['0d59ee240a4cd96ddbb4ff164fccea4d'] = true; + // already loaded by bootstrap inside the hrtime condition + // require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php73/Php73.php'; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php73/bootstrap.php'; + } + + if ( + PHP_VERSION_ID < 70400 + && empty($GLOBALS['__composer_autoload_files']['b686b8e46447868025a15ce5d0cb2634']) + && !class_exists(\Symfony\Polyfill\Php74\Php74::class, false) + ) { + $GLOBALS['__composer_autoload_files']['b686b8e46447868025a15ce5d0cb2634'] = true; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php74/Php74.php'; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php74/bootstrap.php'; + } + + if ( + !extension_loaded('intl') + && empty($GLOBALS['__composer_autoload_files']['8825ede83f2f289127722d4e842cf7e8']) + && !class_exists(\Symfony\Polyfill\Intl\Grapheme\Grapheme::class, false) + ) { + $GLOBALS['__composer_autoload_files']['8825ede83f2f289127722d4e842cf7e8'] = true; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-intl-grapheme/Grapheme.php'; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-intl-grapheme/bootstrap.php'; + } + + if ( + PHP_VERSION_ID < 80100 + && empty ($GLOBALS['__composer_autoload_files']['23c18046f52bef3eea034657bafda50f']) + && !class_exists(\Symfony\Polyfill\Php81\Php81::class, false) + ) { + $GLOBALS['__composer_autoload_files']['23c18046f52bef3eea034657bafda50f'] = true; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php81/Php81.php'; + require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php81/bootstrap.php'; + } + } + + $filename = str_replace('\\', DIRECTORY_SEPARATOR, $class); + if (strpos($class, 'PHPStan\\BetterReflection\\') === 0) { + $filename = substr($filename, strlen('PHPStan\\BetterReflection\\')); + $filepath = 'phar://' . __DIR__ . '/phpstan.phar/vendor/ondrejmirtes/better-reflection/src/' . $filename . '.php'; + } else { + $filename = substr($filename, strlen('PHPStan\\')); + $filepath = 'phar://' . __DIR__ . '/phpstan.phar/src/' . $filename . '.php'; + } + + if (!file_exists($filepath)) { + return; + } + + require $filepath; + } +} + +spl_autoload_register([PharAutoloader::class, 'loadClass']); diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan/composer.json b/new/apps/web/src/php/vendor/phpstan/phpstan/composer.json new file mode 100644 index 0000000..07faa85 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan/composer.json @@ -0,0 +1,26 @@ +{ + "name": "phpstan/phpstan", + "description": "PHPStan - PHP Static Analysis Tool", + "license": ["MIT"], + "keywords": ["dev", "static analysis"], + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "autoload": { + "files": ["bootstrap.php"] + }, + "support": { + "issues": "https://github.com/phpstan/phpstan/issues", + "forum": "https://github.com/phpstan/phpstan/discussions", + "source": "https://github.com/phpstan/phpstan-src", + "docs": "https://phpstan.org/user-guide/getting-started", + "security": "https://github.com/phpstan/phpstan/security/policy" + } +} diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan/conf/bleedingEdge.neon b/new/apps/web/src/php/vendor/phpstan/phpstan/conf/bleedingEdge.neon new file mode 100644 index 0000000..01fee97 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan/conf/bleedingEdge.neon @@ -0,0 +1,2 @@ +includes: + - phar://phpstan.phar/conf/bleedingEdge.neon diff --git a/new/apps/web/src/php/vendor/phpstan/phpstan/phpstan b/new/apps/web/src/php/vendor/phpstan/phpstan/phpstan new file mode 100755 index 0000000..7a08ef4 --- /dev/null +++ b/new/apps/web/src/php/vendor/phpstan/phpstan/phpstan @@ -0,0 +1,8 @@ +#!/usr/bin/env php + time() + ) { + $validversions = $validversions . $eolitem['latest'] . ' '; + } +} + +$thisBuildInt = (int) substr($json_data['BasicInfo']['Version'], 5); +$latestBuildInt = (int) substr($latestver, 5); + +// EOL +$eoltext = ''; +$os_insider = false; +if (strpos($validversions, $json_data['BasicInfo']['Version']) !== false) { + $eoltext = "Not EOL"; + $eolcolor = "green"; +} else if ($thisBuildInt > $latestBuildInt) { + $os_insider = true; + $eoltext = 'Insider'; + $eolcolor = "green"; +} else { + $eoltext = "EOL"; + $eolcolor = "red"; +} + +// Up-to-Date-ness +$oscheck = ''; +if (strpos($latestver, $json_data['BasicInfo']['Version']) !== false) { + $oscheck = 'Up-to-date'; + $oscolor = "green"; +} else { + $oscheck = 'Not Up-to-Date'; + $oscolor = "red"; +} + +//The lines below are for the loop that calculates total RAM/CPU used. +//CPU doesn't work right now because we are not able to efficiently get the CPU usage of each running process. +$working_set = 0; +$cpu_percent = 0; + +foreach ($json_data['System']['RunningProcesses'] as $process) { + $working_set += $process['WorkingSet']; // RAM + $cpu_percent += $process['WorkingSet']; // CPU +} + +$ram_used = number_format($working_set / 1073741824, 2, '.', ''); + +$total_ram = 0; + +if (isset($json_data['Hardware']['Ram'])) { + //Don't ask me why this is an old fashioned for loop, I got carried away. + //Getting the total amount of RAM in the system. + $ram_sticks = safe_count($json_data['Hardware']['Ram']); + + foreach ($json_data['Hardware']['Ram'] as $stick) { + $capacity = $stick['Capacity']; + if ($capacity != 0) { + $ram_size = floor($stick['Capacity'] / 1000); + $total_ram += $ram_size; + } + } + //Calculating how much of it is used + $ram_used_percent = round((float)$ram_used / (float)$total_ram * 100); +} + +//Trimming the motherboard manufacturer string after the first space. +$motherboard = strtok($json_data['Hardware']['Motherboard']['Manufacturer'], " "); + +//Basic string to time php function to take the generation date and turn it into a usable format. +$ds = strtotime($json_data['Meta']['GenerationDate']); +$test_time = timeConvert($json_data['BasicInfo']['Uptime']); + +//Uservar paths split function +$paths = $json_data['System']['UserVariables']['Path']; + +// Split the paths into an array using the semicolon as the delimiter +$path_array = explode(';', $paths); + + +//PUP check +include('lists.php'); +// Set up the reference list +$referenceListInstalled = $json_data['System']['InstalledApps']; +$referenceListRunning = $json_data['System']['RunningProcesses']; + +$pupsfoundInstalled = array(); +foreach ($referenceListInstalled as $installed) { + foreach ($notableSoftwareList as $pups) { + preg_match('/\b(' . strtolower($pups) . ')\b/', strtolower($installed['Name']), $matches, PREG_OFFSET_CAPTURE); + if ($matches) { + array_push($pupsfoundInstalled, $installed['Name']); + } + } +} +$pupsfoundInstalled = array_unique($pupsfoundInstalled); + +$pupsfoundRunning = array(); +foreach ($referenceListRunning as $running) { + foreach ($notableSoftwareList as $pups) { + preg_match('/\b(' . strtolower($pups) . ')\b/', strtolower($running['ProcessName']), $matches, PREG_OFFSET_CAPTURE); + if ($matches) { + array_push($pupsfoundRunning, $running['ProcessName']); + } + } +} +$pupsfoundRunning = array_unique($pupsfoundRunning); + +// Old PUP Filter +/* +$pupsfoundInstalled = array_filter($referenceListInstalled, function ($checkobj) use ($normalizedArray) { + foreach ($normalizedArray as $pup) { + if (str_contains(strtolower($checkobj['Name']), $pup)) { + return $checkobj; + } + } +}); + +$pupsfoundRunning = array_filter($referenceListRunning, function($checkobj) use ($normalizedArray){ + foreach ($normalizedArray as $pup) { + if (str_contains(strtolower($checkobj['ProcessName']), $pup)) { + return $checkobj; + } + } +}); +*/ +?> + + + + + + + Profile <?= $profile_name ?> | Specified + + + + + + + + + + " /> + + " /> + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + + + + + + + '; + } + } + ?> + +
+
+ + +
+
+
+
+
+
+ Profile created + , runtime + + Under Specify Version + +
+ +
+
+ + Massive Shoutout to Spark +
+ + + \ No newline at end of file diff --git a/new/apps/web/src/php/widgets.php b/new/apps/web/src/php/widgets.php new file mode 100644 index 0000000..957bab4 --- /dev/null +++ b/new/apps/web/src/php/widgets.php @@ -0,0 +1,1235 @@ + + +
+ $drive) { + $drive_size_raw = $drive['DiskCapacity']; + $drive_free_raw = getDriveFree($drive); + $device_name = $drive['DeviceName']; + $drive_taken_raw = $drive_size_raw - $drive_free_raw; + $drive_size = floor(bytesToGigabytes($drive_size_raw)); + $drive_taken = floor(bytesToGigabytes($drive_taken_raw)); + // the drive size can sometimes be zero if the drive is failing + if ($drive_taken != 0 && $drive_size != 0) { + $drive_percentage = round($drive_taken / $drive_size * 100); + } else $drive_percentage = 0; + $flavor_color = ''; + + if ($drive_percentage >= 80) { + $flavor_color = "red"; + } elseif ($drive_percentage >= 50 && $drive_percentage <= 79) { + $flavor_color = "yellow"; + } elseif ($drive_percentage >= 0 && $drive_percentage <= 49) { + $flavor_color = "green"; + } + if (abs(floor(bytesToGigabytes($drive['DiskCapacity'])) - + floor(bytesToGigabytes(getDriveCapacity($drive)))) > 5) { + $flavor_color = "red"; + } + + $letters = array_filter( + array_column($drive['Partitions'], 'PartitionLetter') + ); + $lettersString = implode(", ", $letters); + + echo ' +
+

' . $device_name . ' ' . $lettersString . '

+
+
+
+ ' . (int)$drive_taken . ' GB + / + ' . (int) $drive_size . ' GB +
+
' . $drive_percentage . '%
+
+
+
+ '; + } + ?> +
+
+
+

CPU + (Used) +

+
+
+
+ + % + +
+
+
+
+
+

Memory + (Used) +

+
+
+
+ + GB + + / + + GB + +
+
+ % +
+
+
+
+
+

Temps

+
+
+
🔥
+
C
+
+
+
+ +
+

Audio Devices

+
+ Internal : ' . $internalaudio . '
'; + echo '
External : ' . $externalaudio . '
'; + ?> +
+
+ +
+

Power Profile/Battery +

+
+
+
+ + ' . $current_profile . ''; + } + } + ?> +
Current Profile
+
+
+
+
+ +
\ No newline at end of file