Compare commits
No commits in common. "master" and "0.2.7.43" have entirely different histories.
|
@ -25,7 +25,6 @@ after_build:
|
||||||
#- cmd: xcopy /s /y WelsonJS.Toolkit\WelsonJS.Toolkit\bin\x86\%CONFIGURATION%\* artifacts\
|
#- cmd: xcopy /s /y WelsonJS.Toolkit\WelsonJS.Toolkit\bin\x86\%CONFIGURATION%\* artifacts\
|
||||||
- cmd: xcopy /s /y WelsonJS.Toolkit\WelsonJS.Service\bin\x86\%CONFIGURATION%\* artifacts\
|
- cmd: xcopy /s /y WelsonJS.Toolkit\WelsonJS.Service\bin\x86\%CONFIGURATION%\* artifacts\
|
||||||
- cmd: xcopy /s /y WelsonJS.Toolkit\WelsonJS.Launcher\bin\x86\%CONFIGURATION%\* artifacts\
|
- cmd: xcopy /s /y WelsonJS.Toolkit\WelsonJS.Launcher\bin\x86\%CONFIGURATION%\* artifacts\
|
||||||
- cmd: nuget pack WelsonJS.Toolkit\WelsonJS.Toolkit\ -properties Configuration=%CONFIGURATION% -properties Platform=x86 -OutputDirectory artifacts\
|
|
||||||
- cmd: 7z a artifacts.zip artifacts\*
|
- cmd: 7z a artifacts.zip artifacts\*
|
||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
|
|
2
.github/FUNDING.yml
vendored
|
@ -1,2 +0,0 @@
|
||||||
github: gnh1201
|
|
||||||
custom: ['https://gnh1201.link']
|
|
8
.github/workflows/codeql-analysis.yml
vendored
|
@ -32,7 +32,7 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
language: [ 'javascript' ]
|
language: [ 'csharp', 'javascript', 'python' ]
|
||||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||||
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ jobs:
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v2
|
uses: github/codeql-action/init@v1
|
||||||
with:
|
with:
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
|
@ -53,7 +53,7 @@ jobs:
|
||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
# If this step fails, then you should remove it and run the build manually (see below)
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@v2
|
uses: github/codeql-action/autobuild@v1
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# 📚 https://git.io/JvXDl
|
# 📚 https://git.io/JvXDl
|
||||||
|
@ -67,4 +67,4 @@ jobs:
|
||||||
# make release
|
# make release
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v2
|
uses: github/codeql-action/analyze@v1
|
||||||
|
|
23
.github/workflows/llm-code-review.yml
vendored
|
@ -1,23 +0,0 @@
|
||||||
name: AI Code Review
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, reopened]
|
|
||||||
issues:
|
|
||||||
types: [opened, reopened]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
repofix:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Run RepoFixAI
|
|
||||||
uses: Manav916/llm-code-review@main
|
|
||||||
with:
|
|
||||||
groq_api_key: ${{ secrets.GROQ_API_KEY }}
|
|
||||||
groq_model: 'llama-3.3-70b-versatile'
|
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
# exclude_extensions: 'txt'
|
|
||||||
repo_owner: ${{ github.repository_owner }}
|
|
||||||
repo_name: ${{ github.event.repository.name }}
|
|
||||||
event_number: ${{ github.event.number || github.event.issue.number }} # when listening for both pull requests and issues
|
|
||||||
event_name: ${{ github.event_name }}
|
|
6
.gitignore
vendored
|
@ -103,13 +103,11 @@ dist
|
||||||
# TernJS port file
|
# TernJS port file
|
||||||
.tern-port
|
.tern-port
|
||||||
|
|
||||||
# user private assets
|
# user defined assets
|
||||||
bin
|
bin
|
||||||
data/*-apikey.txt
|
data/chatgpt-apikey.txt
|
||||||
data/*.nomedia.txt
|
|
||||||
app/assets/img/_templates
|
app/assets/img/_templates
|
||||||
app/assets/img/_captured
|
app/assets/img/_captured
|
||||||
settings.ini
|
settings.ini
|
||||||
defaultService.js
|
defaultService.js
|
||||||
lib/*.private.js
|
lib/*.private.js
|
||||||
data/python313.zip
|
|
||||||
|
|
6
FUNDING.yml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
github: gnh1201
|
||||||
|
open_collective: welsonjs
|
||||||
|
liberapay: catswords
|
||||||
|
custom: ['https://www.buymeacoffee.com/catswords']
|
||||||
|
patreon: catswords
|
||||||
|
ko_fi: catswords
|
235
README.md
|
@ -2,83 +2,101 @@
|
||||||
|
|
||||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2Fgnh1201%2Fwelsonjs?ref=badge_shield)
|
[](https://app.fossa.com/projects/git%2Bgithub.com%2Fgnh1201%2Fwelsonjs?ref=badge_shield)
|
||||||
[](https://ci.appveyor.com/project/gnh1201/welsonjs)
|
[](https://ci.appveyor.com/project/gnh1201/welsonjs)
|
||||||
[](https://doi.org/10.5281/zenodo.11382384)
|
[](https://doi.org/10.5281/zenodo.11382384)
|
||||||
[](https://catswords-oss.rdbl.io/5719744820/5510319392)
|
|
||||||
[](https://catswords-oss.rdbl.io/5719744820/5510319392)
|
|
||||||
[](https://catswords-oss.rdbl.io/5719744820/5510319392)
|
|
||||||
[](https://catswords-oss.rdbl.io/5719744820/5510319392)
|
|
||||||
[](https://www.slideshare.net/slideshow/welsonjs-javascript-framework-presentation-2024/276005486)
|
|
||||||
[](https://youtu.be/JavH7Dms8-U)
|
|
||||||
[](https://discord.gg/XKG5CjtXEj)
|
|
||||||
[](https://github.com/gnh1201/welsonjs/discussions/167)
|
|
||||||
|
|
||||||
<img src="app/assets/img/logo.svg" height="32" alt=""/> WelsonJS - Build a Windows app on the Windows built-in JavaScript engine.
|
<img src="app/assets/img/logo.svg" height="32" alt=""/> WelsonJS - Build a Windows app on the Windows built-in JavaScript engine.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Now, You can build a Windows desktop app with JavaScript, TypeScript, CoffeeScript, ReScript, and HTML/CSS on Windows built-in ECMAScript engine.
|
Now, You can build an Windows desktop app with JavaScript, TypeScript, CoffeeScript, ReScript, and HTML/CSS on Windows built-in ECMAScript engine.
|
||||||
|
|
||||||
WelsonJS = ***W***indows + ***El***ectr***on***-like + ***Javascript(JS)*** + :heart:[Contributions](https://github.com/sponsors/gnh1201)
|
WelsonJS = ***W***indows + ***El***ectr***on***-like + ***Javascript(JS)*** + [Your contribution](https://github.com/sponsors/gnh1201)
|
||||||
|
|
||||||
* :kissing_cat: [Download Latest WelsonJS Launcher (ics.catswords.net)](https://ics.catswords.net/welsonjs_launcher_latest.zip)
|
Dual license notice: The default license for this project is GPL 3.0. However, if the GPL 3.0 license is not compatible with Microsoft products, it is subject to the MS-RL license.
|
||||||
* :rocket: [Launch the WelsonJS environment on Microsoft Azure (azuremarketplace.microsoft.com)](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/catswords.catswords-welsonjs-feb2025-02?tab=Overview)
|
|
||||||
|
|
||||||
**Note**: The default license for this project is GPL 3.0. However, if the GPL 3.0 license is not compatible with Microsoft products, it is subject to the MS-RL license.
|
|
||||||
|
|
||||||
## Sponsors
|
## Sponsors
|
||||||
* :octocat: [GitHub Sponsors](https://github.com/sponsors/gnh1201), :coffee: [Buy me a coffee](https://buymeacoffee.com/catswords)
|
- <img src="app/assets/img/github_octocat_logo.png" height="32" alt=""/> [GitHub Sponsors](https://github.com/sponsors/gnh1201)
|
||||||
* <img src="https://ics.catswords.net/logo_oss.gif" height="32" alt=""/> [Open SW Portal](https://oss.kr), NIPA National IT Industry Promotion Agency<sup>(정보통신산업진흥원)</sup>
|
- <img src="app/assets/img/logo_oss.gif" height="32" alt=""/> Open Software Portal, Korea National Industry Promotion Agency - Awarded Prize
|
||||||
* <img src="https://ics.catswords.net/signpath_logo.png" height="32" alt=""/> Free code signing provided by [SignPath.io](https://signpath.io), certificate by [SignPath Foundation](https://signpath.org/)
|
- <img src="app/assets/img/signpath_logo.png" height="32" alt=""/> Free code signing provided by [SignPath.io](https://signpath.io), certificate by [SignPath Foundation](https://signpath.org/)
|
||||||
* <img src="https://ics.catswords.net/f1security_logo.png" height="32" alt=""/> [F1Security<sup>(에프원시큐리티)</sup>](https://f1security.co.kr/) provides [industry-leading](https://www.ksecurity.or.kr/kisis/subIndex/469.do) web security services.
|
|
||||||
* <img src="https://ics.catswords.net/microsoft_logo.png" height="32" alt=""/> [Microsoft ISV Success Program](https://www.microsoft.com/en-us/isv/isv-success), Grow your business with powerful tools.
|
|
||||||
* :zap: [Integrations](https://catswords-oss.rdbl.io/5719744820/8278298336) ([ScrapeOps](https://scrapeops.io?fpr=namhyeon75), [SearchApi](https://www.searchapi.io/?via=namhyeon), [AviationStack](https://aviationstack.com?utm_source=FirstPromoter&utm_medium=Affiliate&fpr=namhyeon71), [Coupang](https://link.coupang.com/a/b7HV3V)...)
|
|
||||||
|
|
||||||
## System Requirements
|
## [Partnerships](https://github.com/gnh1201/welsonjs/wiki/Partnerships)
|
||||||
* **Operating Systems**: Windows XP SP3 or later (Currently, Windows 11 24H2)
|
- [<img src="app/assets/img/scrapeops-logo.svg" height="32" alt=""/> ScrapeOps (scrapeops.io)](https://scrapeops.io?fpr=namhyeon75) - Proxy Aggregator (1,000 free calls/month, [10% discount coupon](https://github.com/gnh1201/welsonjs/wiki/Partnerships))
|
||||||
* For systems running Windows 2000 or earlier versions (e.g., 95, 98, Me), please contact us separately.
|
- [<img src="app/assets/img/searchapi-logo.svg" height="32" alt="SearchApi"/> (searchapi.io)](https://www.searchapi.io/?via=namhyeon) - SERP (Google, Bing, Baidu, Amazon, YouTube, App Store (Google, Apple), etc.) scraping (100 free calls/month)
|
||||||
|
|
||||||
## Why Choose WelsonJS?
|
|
||||||
WelsonJS is an advanced JavaScript framework designed to operate in extreme conditions where conventional solutions may fail. Unlike traditional JavaScript frameworks, WelsonJS focuses on executing scripts in constrained environments, ensuring reliable performance even with minimal system resources.
|
|
||||||
|
|
||||||
### Key Features
|
|
||||||
* **Lightweight and Efficient**: Optimized for environments with limited computing power, WelsonJS delivers efficient script execution without unnecessary overhead.
|
|
||||||
* **Windows ECMAScript Compatibility**: Designed to run seamlessly on Windows-based systems, adhering to the ECMAScript standard while maintaining lightweight execution.
|
|
||||||
* **Standalone Execution**: Unlike well-known JavaScript runtimes, which require external dependencies, a WelsonJS application can operate as a self-contained app, making it suitable for embedded systems and isolated environments.
|
|
||||||
* **Security-Oriented**: Built with security in mind, ensuring controlled execution of scripts without compromising system integrity.
|
|
||||||
* **Minimalist Design**: WelsonJS strips away unnecessary complexities, focusing on core functionalities that maximize performance and reliability.
|
|
||||||
|
|
||||||
### Use Cases
|
|
||||||
* **Legacy System Integration**: WelsonJS provides a practical solution for running JavaScript on older Windows environments where modern frameworks are not feasible.
|
|
||||||
* **Automation and Scripting**: Ideal for executing scripts in constrained environments, enabling automated workflows and system-level scripting.
|
|
||||||
* **Embedded Applications**: Suitable for devices and systems with strict resource constraints, such as industrial controllers and embedded platforms.
|
|
||||||
* **Security-Focused Environments**: Useful in security-sensitive applications where dependencies on external network connections are limited.
|
|
||||||
* **Office Automation**: Suitable for office automation tasks using Microsoft Office and various LLM-based AI (such as ChatGPT).
|
|
||||||
|
|
||||||
WelsonJS is tailored for developers who need a reliable, lightweight JavaScript framework in environments where traditional solutions are impractical. Whether working with legacy systems, embedded devices, or security-critical applications, WelsonJS ensures that JavaScript remains a viable and efficient option.
|
|
||||||
|
|
||||||
## Structure
|
## Structure
|
||||||

|

|
||||||
|
|
||||||
## Specifications
|
## Specifications
|
||||||
* Built-in transpilers: [TypeScript](https://www.typescriptlang.org/), [Rescript](https://rescript-lang.org/), [CoffeeScript 2](https://coffeescript.org/), [LiveScript](https://livescript.net/)
|
- Built-in transpilers: [TypeScript](https://www.typescriptlang.org/), [Rescript](https://rescript-lang.org/), [CoffeeScript 2](https://coffeescript.org/), [LiveScript](https://livescript.net/)
|
||||||
* **Ready to use on Windows machine immediately. No additional software installation is required.**
|
- Ready to use on Windows machine immediately. No require additional software installation.
|
||||||
* **WelsonJS Launcher**: Manage instances (Like a container), User-defined variable editor, [Microsoft Monaco Editor](https://github.com/microsoft/monaco-editor) and [React](https://react.dev/) (Pre-embedded rich code editor), [Microsoft Copilot](https://copilot.microsoft.com), and [Azure AI Services](https://azure.microsoft.com/en-us/products/ai-services), Network tools (Whois, DNS Query, [Criminal IP CTI](https://www.criminalip.io/)) on the code editor.
|
- ES5(ECMAScript 5), XML, JSON, YAML compatibility
|
||||||
* ES5(ECMAScript 5), XML, JSON, YAML compatibility: [core-js](https://github.com/zloirock/core-js), [JSON2.js](https://github.com/douglascrockford/JSON-js), [js-yaml](https://github.com/nodeca/js-yaml)
|
- [github.com/zloirock/core-js](https://github.com/zloirock/core-js)
|
||||||
* HTML5 compatibility on the built-in HTML rendering engine: [html5shiv](https://github.com/aFarkas/html5shiv), [jquery-html5-placeholder-shim](https://github.com/parndt/jquery-html5-placeholder-shim), [Respond](https://github.com/scottjehl/Respond), [selectivizr](https://github.com/keithclark/selectivizr), [ExplorerCanvas](https://github.com/arv/ExplorerCanvas), [Modernizr](https://github.com/Modernizr/Modernizr)
|
- [github.com/douglascrockford/JSON-js](https://github.com/douglascrockford/JSON-js) (aka. JSON2.js)
|
||||||
* Classical CSS Frameworks: [cascadeframework](https://github.com/jslegers/cascadeframework), [golden-layout](https://github.com/golden-layout/golden-layout)
|
- [github.com/nodeca/js-yaml](https://github.com/nodeca/js-yaml)
|
||||||
* WYSIWYG HTML Editor: [summernote](https://github.com/summernote/summernote)
|
- HTML5, CSS3 compatibility
|
||||||
* Included libraries: [jQuery](https://jquery.com/), [jQuery UI](https://jqueryui.com/), [jquery-toast-plugin](https://github.com/kamranahmedse/jquery-toast-plugin), [squel](https://github.com/hiddentao/squel), [jsrender](https://github.com/BorisMoore/jsrender), [linq](https://github.com/mihaifm/linq), [pegjs](https://github.com/pegjs/pegjs), [numbers.js](https://github.com/numbers/numbers.js)
|
- [github.com/aFarkas/html5shiv](https://github.com/aFarkas/html5shiv)
|
||||||
* Compatible with modern JavaScript specifications: [module.exports](https://nodejs.org/api/modules.html#moduleexports), CommonJS, UMD compatibility, [NPM(Node Package Manager)](https://www.npmjs.com/) compatibility
|
- [github.com/parndt/jquery-html5-placeholder-shim](https://github.com/parndt/jquery-html5-placeholder-shim)
|
||||||
* Support a device debugging protocol clients: [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/), [ADB(Android Debug Bridge)](https://source.android.com/docs/setup/build/adb)
|
- [github.com/scottjehl/Respond](https://github.com/scottjehl/Respond)
|
||||||
* RPC(Remote Procedure Call) protocol clients: [gRPC](https://grpc.io/), [JSON-RPC 2.0](https://www.jsonrpc.org/specification)
|
- [github.com/keithclark/selectivizr](https://github.com/keithclark/selectivizr)
|
||||||
* Various types of HTTP clients: [XHR(MSXML)](https://developer.mozilla.org/docs/Glossary/XMLHttpRequest), [cURL](https://curl.se/), [BITS](https://en.m.wikipedia.org/w/index.php?title=Background_Intelligent_Transfer_Service), [CERT](https://github.com/MicrosoftDocs/windowsserverdocs/blob/main/WindowsServerDocs/administration/windows-commands/certutil.md), [Web Proxy, SEO/SERP](https://catswords-oss.rdbl.io/5719744820/1706431912)
|
- [github.com/arv/ExplorerCanvas](https://github.com/arv/ExplorerCanvas)
|
||||||
* The native toolkit for Windows environments: Write a Windows Service Application with JavaScript, Control a window handle, Cryptography (e.g., [ISO/IEC 18033-3:2010](https://www.iso.org/standard/54531.html) aka. [HIGHT](https://seed.kisa.or.kr/kisa/algorithm/EgovHightInfo.do)), [Named Shared Memory](https://learn.microsoft.com/en-us/windows/win32/memory/creating-named-shared-memory) based [IPC](https://qiita.com/gnh1201/items/4e70dccdb7adacf0ace5), [NuGet package](https://www.nuget.org/packages/WelsonJS.Toolkit)
|
- [github.com/Modernizr/Modernizr](https://github.com/Modernizr/Modernizr)
|
||||||
* Generative AI integrations: [Multiple LLM and sLLM](https://catswords-oss.rdbl.io/5719744820/5510319392) (e.g., ChatGPT, Claude, ...)
|
- CSS Frameworks
|
||||||
* Aviation Data integrations: [AviationStack](https://aviationstack.com?utm_source=FirstPromoter&utm_medium=Affiliate&fpr=namhyeon71), [SearchApi Google Flight](https://www.searchapi.io/?via=namhyeon)
|
- [github.com/jslegers/cascadeframework](https://github.com/jslegers/cascadeframework)
|
||||||
* VM infrastructure tool integrations: [OVFTool for Broadcom/VMware infrastructures](https://developer.broadcom.com/tools/open-virtualization-format-ovf-tool/latest)
|
- [github.com/golden-layout/golden-layout](https://github.com/golden-layout/golden-layout)
|
||||||
* Everything you can imagine.
|
- WYSIWYG HTML Editor
|
||||||
|
- [github.com/summernote/summernote](https://github.com/summernote/summernote)
|
||||||
|
- Included libraries
|
||||||
|
- [jQuery](https://jquery.com/)
|
||||||
|
- [jQuery UI](https://jqueryui.com/)
|
||||||
|
- [github.com/kamranahmedse/jquery-toast-plugin](https://github.com/kamranahmedse/jquery-toast-plugin) - Highly customizable jquery plugin to show toast messages
|
||||||
|
- [github.com/hiddentao/squel](https://github.com/hiddentao/squel) - SQL query string builder for Javascript
|
||||||
|
- [github.com/BorisMoore/jsrender](https://github.com/BorisMoore/jsrender) - A lightweight, powerful and highly extensible templating engine. In the browser or on Node.js, with or without jQuery.
|
||||||
|
- [github.com/mihaifm/linq](https://github.com/mihaifm/linq) - LINQ for JavaScript
|
||||||
|
- [github.com/pegjs/pegjs](https://github.com/pegjs/pegjs) - PEG.js: Parser generator for JavaScript
|
||||||
|
- [Includes binaries](https://github.com/gnh1201/welsonjs/blob/master/bin/README.MD)
|
||||||
|
- [module.exports](https://nodejs.org/api/modules.html#moduleexports), CommonJS, UMD compatibility
|
||||||
|
- [NPM](https://www.npmjs.com/) compatibility
|
||||||
|
- [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/) support
|
||||||
|
- [ADB(Android Debug Bridge)](https://source.android.com/docs/setup/build/adb) support
|
||||||
|
- RPC(Remote Procedure Call) protocol support
|
||||||
|
- [gRPC](https://grpc.io/)
|
||||||
|
- [JSON-RPC 2.0](https://www.jsonrpc.org/specification)
|
||||||
|
|
||||||
## Quick start
|
## Included modules
|
||||||
|
- lib/std (Standard library)
|
||||||
|
- lib/system (System interface)
|
||||||
|
- lib/base64 (BASE64 encode and decode)
|
||||||
|
- lib/file (File I/O interface)
|
||||||
|
- lib/http (HTTP/HTTPS client with [XHR(MSXML)](https://developer.mozilla.org/docs/Glossary/XMLHttpRequest), [cURL](https://curl.se/), [BITS](https://en.m.wikipedia.org/w/index.php?title=Background_Intelligent_Transfer_Service), [CERT](https://github.com/MicrosoftDocs/windowsserverdocs/blob/main/WindowsServerDocs/administration/windows-commands/certutil.md), and [Web Proxy API](https://scrapeops.io?fpr=namhyeon75))
|
||||||
|
- lib/registry (Windows Registry interface)
|
||||||
|
- lib/security (Windows Security Policy interface)
|
||||||
|
- lib/shell (Windows Shell (Command Prompt) interface)
|
||||||
|
- lib/powershell (Windows Powershell interface)
|
||||||
|
- lib/service (Windows Service interface)
|
||||||
|
- lib/browser (Modern web compatibility layer)
|
||||||
|
- lib/uri (URI scheme interface)
|
||||||
|
- lib/winlibs (Windows DLL(Dynamic-link library) interface)
|
||||||
|
- lib/autohotkey ([AutoHotkey](https://www.autohotkey.com/) interface)
|
||||||
|
- lib/autoit ([AutoIt3/AutoItX](https://www.autoitscript.com/) interface)
|
||||||
|
- lib/msoffice (Microsoft Office (e.g. Excel, PowerPoint, Word) interface)
|
||||||
|
- lib/gtk (GTK-server and GladeXML supported GUI interface)
|
||||||
|
- lib/chrome ([Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/) based Chrome/Chromium web browser testing interface)
|
||||||
|
- lib/pipe-ipc (PIPE (e.g., File IO, Standard IO) based IPC(Inter-Process Communication) implementation)
|
||||||
|
- [WelsonJS.Toolkit](https://github.com/gnh1201/welsonjs/wiki/Awesome-binaries) (DLL/COM component with .NET 2.0, For all Windows based systems)
|
||||||
|
- User prompt methods (e.g., alert, confirm) implementation
|
||||||
|
- Useful tools to control the windows and window handle (find, attach, trigger events. e.g., Virtual Human Interface
|
||||||
|
- Cryptography ([ISO/IEC 18033-3:2010](https://www.iso.org/standard/54531.html) aka. [HIGHT](https://seed.kisa.or.kr/kisa/algorithm/EgovHightInfo.do))
|
||||||
|
- [Named Shared Memory](https://learn.microsoft.com/en-us/windows/win32/memory/creating-named-shared-memory) based IPC(Inter-Process Communication) implementation [#](https://qiita.com/gnh1201/items/4e70dccdb7adacf0ace5)
|
||||||
|
- [WelsonJS.Service](https://github.com/gnh1201/welsonjs/wiki/Awesome-binaries) (Windows Service Application, For recent Windows based systems)
|
||||||
|
- Write a Windows Service Application with JavaScript
|
||||||
|
- [File Event Monitor](https://github.com/gnh1201/welsonjs/wiki/File-Event-Monitor): Trace file creation, network connections, and registry modifications.
|
||||||
|
- [Screen Time Feature](https://github.com/gnh1201/welsonjs/wiki/Screen-Time-Feature): Find an image position on the computer screens or windows.
|
||||||
|
- [WelsonJS.Launcher](https://github.com/gnh1201/welsonjs/wiki/Launcher) (Launcher Application, For recent Windows based systems)
|
||||||
|
- This is a launcher app designed to easily distribute WelsonJS application packages (based on ZIP compression files).
|
||||||
|
- lib/chatgpt ([ChatGPT](https://openai.com/chatgpt) integration)
|
||||||
|
- Everything you can imagine.
|
||||||
|
|
||||||
|
## Make your own `sayhello` example
|
||||||
|
|
||||||
### 1. Write a file `lib/sayhello.js`
|
### 1. Write a file `lib/sayhello.js`
|
||||||
```js
|
```js
|
||||||
|
@ -89,8 +107,8 @@ function say() {
|
||||||
|
|
||||||
exports.say = say;
|
exports.say = say;
|
||||||
|
|
||||||
exports.VERSIONINFO = "SayHello (sayhello.js) version 0.1";
|
exports.VERSIONINFO = "SayHello Library (sayhello.js) version 0.1";
|
||||||
exports.AUTHOR = "abuse@catswords.net";
|
exports.AUTHOR = "abuse@catswords.net"; // e.g. YOUR EMAIL ADDRESS
|
||||||
exports.global = global;
|
exports.global = global;
|
||||||
exports.require = global.require;
|
exports.require = global.require;
|
||||||
```
|
```
|
||||||
|
@ -109,9 +127,9 @@ function main() {
|
||||||
exports.main = main;
|
exports.main = main;
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Execute script on the console
|
### 3. Execute file on the command prompt
|
||||||
```cmd
|
```cmd
|
||||||
C:\Users\JohnDoe\Documents\GitHub\welsonjs> cscript app.js sayhello
|
C:\Users\knh94\Documents\GitHub\welsonjs> cscript app.js sayhello
|
||||||
calling say()
|
calling say()
|
||||||
hello
|
hello
|
||||||
ended say()
|
ended say()
|
||||||
|
@ -120,62 +138,55 @@ ended say()
|
||||||
## How to release my application?
|
## How to release my application?
|
||||||
The WelsonJS framework suggests the following application release methods:
|
The WelsonJS framework suggests the following application release methods:
|
||||||
|
|
||||||
* **Compress to Zip, and use the launcher**: Compress the files and directories necessary for running the project into a Zip file, and distribute it along with the [WelsonJS Launcher](https://catswords-oss.rdbl.io/5719744820/4131485779).
|
- **Compress to Zip, and use the launcher**: Compress the files and directories necessary for running the project into a Zip file, and distribute it along with the [WelsonJS.Launcher](https://github.com/gnh1201/welsonjs/wiki/Launcher).
|
||||||
* **Build a setup file**: Use [Inno Setup](https://jrsoftware.org/isinfo.php). The setup profile (the `setup.iss` file) is already included.
|
- **Build a setup file**: Use [Inno Setup](https://jrsoftware.org/isinfo.php). Information needed to create the setup file (the `setup.iss` file) is already included.
|
||||||
* **Copy all directories and files**: This is the simplest and most straightforward method.
|
- **Copy all directories and files**: This is the simplest and most straightforward method.
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Thanks to
|
## Thanks to
|
||||||
* :heart: Artwork (Logo image): [@druidesse](https://github.com/druidesse)
|
- Heavy-industry specialized CSP(Cloud Service Provider) in Republic of Korea - Use case establishment
|
||||||
* :heart: Artwork (Cover image): [@_bag0@x.com](https://x.com/_bag0)
|
- Live-commerce specialized online advertisement companies in Republic of Korea - Use case establishment
|
||||||
* :heart: Special Contributors: [@hcho3](https://github.com/hcho3), :octocat: [GitHub Sponsors](https://github.com/sponsors/gnh1201)
|
- Information security companies in Republic of Korea - Use case establishment
|
||||||
* :sunglasses: Heavy-industry specialized CSP(Cloud Service Provider) in Republic of Korea - Use case establishment
|
- <img src="app/assets/img/morioh.svg" height="32" alt=""/> morioh.com - Mentioned
|
||||||
* :sunglasses: Live-commerce specialized online advertisement companies in Republic of Korea - Use case establishment
|
- <img src="app/assets/img/CSDN_Logo.svg" height="32" alt=""/> CSDN - Mentioned
|
||||||
* :sunglasses: Information security companies in Republic of Korea - Use case establishment
|
- <img src="app/assets/img/qiita-logo.png" height="32" alt=""/> Qiita - Knowledge-base about WSH environment
|
||||||
* :eyes: [Facebook Group "Javascript Programming"(javascript4u)](https://www.facebook.com/javascript4u/posts/build-a-windows-desktop-apps-with-javascript-html-and-cssmorioh-javascript-html-/1484014618472735/)
|
- <img src="app/assets/img/RedSky-logo-web.webp" height="32" alt=""/> Redsky Software - PoC(Proof of Concept) of the CommonJS on WSH environment
|
||||||
* :eyes: [morioh.com](https://morioh.com/a/23c427a82bf1/build-a-windows-desktop-apps-with-javascript-html-and-css)
|
- Inspired by a small-sized JavaScript payload demonstrated by a cybersecurity related group.
|
||||||
* :eyes: CSDN
|
- Inspired by the use of Named Shared Memory in an inter-language IPC implementation devised by an unidentified developer.
|
||||||
* :eyes: Qiita - Knowledge-base about WSH environment
|
- <img src="app/assets/img/Fediverse_logo_proposal.svg" height="32" alt=""/> Fediverse - Mentioned
|
||||||
* :sunglasses: Redsky Software - PoC(Proof of Concept) of the CommonJS on WSH environment
|
- <img src="app/assets/img/Hackernews_logo.png" height="32" alt=""/> Hacker News - Mentioned
|
||||||
* :sunglasses: Inspired by a small-sized JavaScript payload demonstrated by a cybersecurity related group.
|
|
||||||
* :sunglasses: Inspired by the use of Named Shared Memory in a cross-runtime IPC implementation written by the unidentified developer.
|
## Related links
|
||||||
* :eyes: Fediverse
|
- [gnh1201/wsh-js-gtk](https://github.com/gnh1201/wsh-js-gtk) - GTK GUI ported to Windows Scripting Host - Javascript (Microsoft JScript) (wsh-js)
|
||||||
* :eyes: [Hacker News](https://news.ycombinator.com/item?id=41316782)
|
- [gnh1201/wsh-json](https://github.com/gnh1201/wsh-json) - JSON stringify/parse (encode/decode) for Windows Scripting Host
|
||||||
* :eyes: [WebToolsWeekly](https://webtoolsweekly.com/archives/issue-585/)
|
- [redskyit/wsh-appjs](https://github.com/redskyit/wsh-appjs) - require-js and app framework for Windows Scripting Host JavaScript
|
||||||
* :eyes: [GeekNews](https://news.hada.io/weekly/202441) in GeekNews Weekly (2024-09-30 ~ 2024-10-06)
|
- [JohnLaTwC's gist](https://gist.github.com/JohnLaTwC/4315bbbd89da0996f5c08c032b391799) - JavaScript RAT
|
||||||
* :eyes: [daily.dev](https://app.daily.dev/posts/js-libraries-svg-tools-json-databases-8quregz3a)
|
- [JSMan-/JS-Framework](https://github.com/JSMan-/JS-Framework) - No description
|
||||||
* :eyes: [PitchHut](https://www.pitchhut.com/project/proj_Ya136OLSW5at)
|
- [iconjack/setTimeout-for-windows-script-host](https://github.com/iconjack/setTimeout-for-windows-script-host) - Replacement for the missing setTimeout and clearTimeout function in Windows Script Host
|
||||||
* :eyes: [Disquiet](https://dis.qa/nv6T6)
|
- [johnjohnsp1/WindowsScriptHostExtension](https://github.com/johnjohnsp1/WindowsScriptHostExtension) - Inject DLL Prototype using Microsoft.Windows.ACTCTX COM Object
|
||||||
|
- [kuntashov/jsunit](https://github.com/kuntashov/jsunit) - JSUnit port for Windows Scripting Host
|
||||||
|
- [nickdoth/WSHHttpServer](https://github.com/nickdoth/WSHHttpServer) - HTTP server based on Windows Script Host
|
||||||
|
- FOSSA report [HTML](https://ics.catswords.net/fossa_report.html) [CSV](https://ics.catswords.net/fossa_report.csv) [TXT](https://ics.catswords.net/fossa_report.txt)
|
||||||
|
- [License attributions of a stock images](https://policy.catswords.social/stock_images.html)
|
||||||
|
|
||||||
## Report abuse
|
## Report abuse
|
||||||
* [GitHub Security Advisories (gnh1201/welsonjs)](https://github.com/gnh1201/welsonjs/security)
|
- [GitHub Security Advisories](https://github.com/gnh1201/welsonjs/security)
|
||||||
* [abuse@catswords.net](mailto:abuse@catswords.net)
|
- abuse@catswords.net
|
||||||
|
- ActivityPub [@catswords_oss@catswords.social](https://catswords.social/@catswords_oss)
|
||||||
## Join the community
|
- XMPP [gnh1201@xmpp.catswords.net](https://policy.catswords.social/xmpp.html)
|
||||||
I am always open. Collaboration, opportunities, and community activities are all welcome.
|
- [Join Catswords on Microsoft Teams](https://teams.live.com/l/community/FEACHncAhq8ldnojAI)
|
||||||
|
|
||||||
* ActivityPub [@catswords_oss@catswords.social](https://catswords.social/@catswords_oss)
|
|
||||||
* XMPP [catswords@conference.omemo.id](xmpp:catswords@conference.omemo.id?join)
|
|
||||||
* [Join Catswords OSS on Microsoft Teams (teams.live.com)](https://teams.live.com/l/community/FEACHncAhq8ldnojAI)
|
|
||||||
* [Join Catswords OSS #welsonjs on Discord (discord.gg)](https://discord.gg/XKG5CjtXEj)
|
|
||||||
|
|
||||||
## Special channels
|
|
||||||
* [A paid consultation channel (m.expert.naver.com)](https://m.expert.naver.com/mobile/expert/product/detail?storeId=100051156&productId=100144540) is available for Korean<sup>(한국어)</sup> region.
|
|
||||||
* [Join the private operations channel (forms.gle)](https://forms.gle/ZKAAaGTiGamksHoo8) is available for all regions.
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2Fgnh1201%2Fwelsonjs?ref=badge_large)
|
[](https://app.fossa.com/projects/git%2Bgithub.com%2Fgnh1201%2Fwelsonjs?ref=badge_large)
|
||||||
|
|
28
SECURITY.MD
|
@ -41,23 +41,15 @@ WelsonJS is a project inspired by the requirements of a cloud service provider t
|
||||||
## Alternative Names
|
## Alternative Names
|
||||||
This program is also known by the following names. These names are used solely for the purpose of identifying the work and do not impact the license:
|
This program is also known by the following names. These names are used solely for the purpose of identifying the work and do not impact the license:
|
||||||
|
|
||||||
* DOI [10.5281/zenodo.11382384](https://zenodo.org/doi/10.5281/zenodo.11382384)(2024) (CERN/OpenAIRE Zenodo)
|
- DOI [10.5281/zenodo.11382384](https://zenodo.org/doi/10.5281/zenodo.11382384) (CERN/OpenAIRE Zenodo)
|
||||||
* ["284757291"](https://ics.catswords.net/1494315-Certificate%2BSoR-284757291.pdf)(2024) (Registered with the [UK Copyright Service](https://copyrightservice.co.uk/))
|
- ["A0562"](https://www.oss.kr/dev_competition_activities/show/544723e6-850a-4956-9194-79640420c19a)(2023) (2023 Open-source Development Contest, NIPA National IT Industry Promotion Agency, Republic of Korea)
|
||||||
* ["A0562"](https://www.oss.kr/dev_competition_activities/show/544723e6-850a-4956-9194-79640420c19a)(2023) (2023 Open-source Development Contest, NIPA National IT Industry Promotion Agency<sup>(정보통신산업진흥원)</sup>, Republic of Korea)
|
- "C-2021-000237"(2021) (Copyright Registration Online System, Korea Copyright Commission, Republic of Korea)
|
||||||
* ["2025-02-08-1952"](https://ics.catswords.net/20250410092300005.pdf)(2025) (Technical Data Bailment System (Technology Escrow), "Korea Foundation for Cooperation of Large & Small Business, Rural Affairs"<sup>(대·중소기업·농어업협력재단)</sup>, Republic of Korea)
|
- "Codename Macadamia"(2020) (Heavy industry specialized CSP in the Republic of Korea)
|
||||||
* "C-2021-000237"(2021) (Copyright Registration Online System, Korea Copyright Commission<sup>(한국저작권위원회)</sup>, Republic of Korea)
|
|
||||||
* "Codename Macadamia"(2020) (Heavy industry specialized CSP in the Republic of Korea)
|
|
||||||
|
|
||||||
## Report abuse
|
## Report Abuse
|
||||||
* [GitHub Security Advisories](https://github.com/gnh1201/welsonjs/security)
|
If you discover any instances of this project being misused, please report them.
|
||||||
* [abuse@catswords.net](mailto:abuse@catswords.net)
|
|
||||||
|
|
||||||
## Join the community
|
- [GitHub Security Advisories](https://github.com/gnh1201/welsonjs/security)
|
||||||
* ActivityPub [@catswords_oss@catswords.social](https://catswords.social/@catswords_oss)
|
- abuse@catswords.net
|
||||||
* XMPP [catswords@conference.omemo.id](xmpp:catswords@conference.omemo.id?join)
|
- ActivityPub: [@catswords_oss@catswords.social](https://catswords.social/@catswords_oss)
|
||||||
* [Join Catswords OSS on Microsoft Teams (teams.live.com)](https://teams.live.com/l/community/FEACHncAhq8ldnojAI)
|
- [Join Catswords on Microsoft Teams](https://teams.live.com/l/community/FEACHncAhq8ldnojAI)
|
||||||
* [Join Catswords OSS #welsonjs on Discord (discord.gg)](https://discord.gg/XKG5CjtXEj)
|
|
||||||
|
|
||||||
## Special channels
|
|
||||||
* [A paid consultation channel (m.expert.naver.com)](https://m.expert.naver.com/mobile/expert/product/detail?storeId=100051156&productId=100144540) is available for Korean<sup>(한국어)</sup> region.
|
|
||||||
* [Join the private operations channel (forms.gle)](https://forms.gle/ZKAAaGTiGamksHoo8) is available for all regions.
|
|
||||||
|
|
261
WelsonJS.Toolkit/WelsonJS.Launcher/EnvForm.Designer.cs
generated
|
@ -1,261 +0,0 @@
|
||||||
namespace WelsonJS.Launcher
|
|
||||||
{
|
|
||||||
partial class EnvForm
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Required designer variable.
|
|
||||||
/// </summary>
|
|
||||||
private System.ComponentModel.IContainer components = null;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Clean up any resources being used.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing && (components != null))
|
|
||||||
{
|
|
||||||
components.Dispose();
|
|
||||||
}
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Windows Form Designer generated code
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Required method for Designer support - do not modify
|
|
||||||
/// the contents of this method with the code editor.
|
|
||||||
/// </summary>
|
|
||||||
private void InitializeComponent()
|
|
||||||
{
|
|
||||||
this.gbUserDefinedVariables = new System.Windows.Forms.GroupBox();
|
|
||||||
this.lvUserDefinedVariables = new System.Windows.Forms.ListView();
|
|
||||||
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
|
||||||
this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
|
||||||
this.gbUpdateUserDefinedVariable = new System.Windows.Forms.GroupBox();
|
|
||||||
this.checkDeleteVariable = new System.Windows.Forms.CheckBox();
|
|
||||||
this.btnOk = new System.Windows.Forms.Button();
|
|
||||||
this.btnOpenFile = new System.Windows.Forms.Button();
|
|
||||||
this.btnOpenDirectory = new System.Windows.Forms.Button();
|
|
||||||
this.textSetValue = new System.Windows.Forms.TextBox();
|
|
||||||
this.textSetName = new System.Windows.Forms.TextBox();
|
|
||||||
this.labelSetValue = new System.Windows.Forms.Label();
|
|
||||||
this.labelSetName = new System.Windows.Forms.Label();
|
|
||||||
this.gbImportAndExport = new System.Windows.Forms.GroupBox();
|
|
||||||
this.btnExport = new System.Windows.Forms.Button();
|
|
||||||
this.btnImport = new System.Windows.Forms.Button();
|
|
||||||
this.gbUserDefinedVariables.SuspendLayout();
|
|
||||||
this.gbUpdateUserDefinedVariable.SuspendLayout();
|
|
||||||
this.gbImportAndExport.SuspendLayout();
|
|
||||||
this.SuspendLayout();
|
|
||||||
//
|
|
||||||
// gbUserDefinedVariables
|
|
||||||
//
|
|
||||||
this.gbUserDefinedVariables.Controls.Add(this.lvUserDefinedVariables);
|
|
||||||
this.gbUserDefinedVariables.Location = new System.Drawing.Point(12, 12);
|
|
||||||
this.gbUserDefinedVariables.Name = "gbUserDefinedVariables";
|
|
||||||
this.gbUserDefinedVariables.Size = new System.Drawing.Size(419, 170);
|
|
||||||
this.gbUserDefinedVariables.TabIndex = 0;
|
|
||||||
this.gbUserDefinedVariables.TabStop = false;
|
|
||||||
this.gbUserDefinedVariables.Text = "User-defined variables";
|
|
||||||
//
|
|
||||||
// lvUserDefinedVariables
|
|
||||||
//
|
|
||||||
this.lvUserDefinedVariables.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
|
|
||||||
this.columnHeader1,
|
|
||||||
this.columnHeader2});
|
|
||||||
this.lvUserDefinedVariables.HideSelection = false;
|
|
||||||
this.lvUserDefinedVariables.Location = new System.Drawing.Point(16, 26);
|
|
||||||
this.lvUserDefinedVariables.Name = "lvUserDefinedVariables";
|
|
||||||
this.lvUserDefinedVariables.Size = new System.Drawing.Size(386, 129);
|
|
||||||
this.lvUserDefinedVariables.TabIndex = 0;
|
|
||||||
this.lvUserDefinedVariables.UseCompatibleStateImageBehavior = false;
|
|
||||||
this.lvUserDefinedVariables.SelectedIndexChanged += new System.EventHandler(this.lvUserDefinedVariables_SelectedIndexChanged);
|
|
||||||
//
|
|
||||||
// columnHeader1
|
|
||||||
//
|
|
||||||
this.columnHeader1.Text = "Name";
|
|
||||||
//
|
|
||||||
// columnHeader2
|
|
||||||
//
|
|
||||||
this.columnHeader2.Text = "Value";
|
|
||||||
//
|
|
||||||
// gbUpdateUserDefinedVariable
|
|
||||||
//
|
|
||||||
this.gbUpdateUserDefinedVariable.Controls.Add(this.checkDeleteVariable);
|
|
||||||
this.gbUpdateUserDefinedVariable.Controls.Add(this.btnOk);
|
|
||||||
this.gbUpdateUserDefinedVariable.Controls.Add(this.btnOpenFile);
|
|
||||||
this.gbUpdateUserDefinedVariable.Controls.Add(this.btnOpenDirectory);
|
|
||||||
this.gbUpdateUserDefinedVariable.Controls.Add(this.textSetValue);
|
|
||||||
this.gbUpdateUserDefinedVariable.Controls.Add(this.textSetName);
|
|
||||||
this.gbUpdateUserDefinedVariable.Controls.Add(this.labelSetValue);
|
|
||||||
this.gbUpdateUserDefinedVariable.Controls.Add(this.labelSetName);
|
|
||||||
this.gbUpdateUserDefinedVariable.Location = new System.Drawing.Point(12, 188);
|
|
||||||
this.gbUpdateUserDefinedVariable.Name = "gbUpdateUserDefinedVariable";
|
|
||||||
this.gbUpdateUserDefinedVariable.Size = new System.Drawing.Size(419, 229);
|
|
||||||
this.gbUpdateUserDefinedVariable.TabIndex = 1;
|
|
||||||
this.gbUpdateUserDefinedVariable.TabStop = false;
|
|
||||||
this.gbUpdateUserDefinedVariable.Text = "Update the user-defined variable";
|
|
||||||
//
|
|
||||||
// checkDeleteVariable
|
|
||||||
//
|
|
||||||
this.checkDeleteVariable.AutoSize = true;
|
|
||||||
this.checkDeleteVariable.Location = new System.Drawing.Point(31, 88);
|
|
||||||
this.checkDeleteVariable.Name = "checkDeleteVariable";
|
|
||||||
this.checkDeleteVariable.Size = new System.Drawing.Size(131, 16);
|
|
||||||
this.checkDeleteVariable.TabIndex = 7;
|
|
||||||
this.checkDeleteVariable.Text = "Delete this variable";
|
|
||||||
this.checkDeleteVariable.UseVisualStyleBackColor = true;
|
|
||||||
//
|
|
||||||
// btnOk
|
|
||||||
//
|
|
||||||
this.btnOk.Image = global::WelsonJS.Launcher.Properties.Resources.icon_check_32;
|
|
||||||
this.btnOk.Location = new System.Drawing.Point(303, 123);
|
|
||||||
this.btnOk.Name = "btnOk";
|
|
||||||
this.btnOk.Size = new System.Drawing.Size(86, 86);
|
|
||||||
this.btnOk.TabIndex = 6;
|
|
||||||
this.btnOk.Text = "Ok";
|
|
||||||
this.btnOk.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
|
|
||||||
this.btnOk.UseVisualStyleBackColor = true;
|
|
||||||
this.btnOk.Click += new System.EventHandler(this.btnOk_Click);
|
|
||||||
//
|
|
||||||
// btnOpenFile
|
|
||||||
//
|
|
||||||
this.btnOpenFile.Image = global::WelsonJS.Launcher.Properties.Resources.icon_file_32;
|
|
||||||
this.btnOpenFile.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
|
||||||
this.btnOpenFile.Location = new System.Drawing.Point(31, 169);
|
|
||||||
this.btnOpenFile.Name = "btnOpenFile";
|
|
||||||
this.btnOpenFile.Padding = new System.Windows.Forms.Padding(11, 0, 0, 0);
|
|
||||||
this.btnOpenFile.Size = new System.Drawing.Size(201, 40);
|
|
||||||
this.btnOpenFile.TabIndex = 5;
|
|
||||||
this.btnOpenFile.Text = "Open the file...";
|
|
||||||
this.btnOpenFile.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
|
||||||
this.btnOpenFile.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
|
|
||||||
this.btnOpenFile.UseVisualStyleBackColor = true;
|
|
||||||
this.btnOpenFile.Click += new System.EventHandler(this.btnOpenFile_Click);
|
|
||||||
//
|
|
||||||
// btnOpenDirectory
|
|
||||||
//
|
|
||||||
this.btnOpenDirectory.Image = global::WelsonJS.Launcher.Properties.Resources.icon_directory_32;
|
|
||||||
this.btnOpenDirectory.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
|
||||||
this.btnOpenDirectory.Location = new System.Drawing.Point(31, 123);
|
|
||||||
this.btnOpenDirectory.Name = "btnOpenDirectory";
|
|
||||||
this.btnOpenDirectory.Padding = new System.Windows.Forms.Padding(11, 0, 0, 0);
|
|
||||||
this.btnOpenDirectory.Size = new System.Drawing.Size(201, 40);
|
|
||||||
this.btnOpenDirectory.TabIndex = 4;
|
|
||||||
this.btnOpenDirectory.Text = "Open the directory...";
|
|
||||||
this.btnOpenDirectory.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
|
||||||
this.btnOpenDirectory.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
|
|
||||||
this.btnOpenDirectory.UseVisualStyleBackColor = true;
|
|
||||||
this.btnOpenDirectory.Click += new System.EventHandler(this.btnOpenDirectory_Click);
|
|
||||||
//
|
|
||||||
// textSetValue
|
|
||||||
//
|
|
||||||
this.textSetValue.Location = new System.Drawing.Point(98, 55);
|
|
||||||
this.textSetValue.Name = "textSetValue";
|
|
||||||
this.textSetValue.Size = new System.Drawing.Size(291, 21);
|
|
||||||
this.textSetValue.TabIndex = 3;
|
|
||||||
//
|
|
||||||
// textSetName
|
|
||||||
//
|
|
||||||
this.textSetName.Location = new System.Drawing.Point(98, 28);
|
|
||||||
this.textSetName.Name = "textSetName";
|
|
||||||
this.textSetName.Size = new System.Drawing.Size(291, 21);
|
|
||||||
this.textSetName.TabIndex = 2;
|
|
||||||
//
|
|
||||||
// labelSetValue
|
|
||||||
//
|
|
||||||
this.labelSetValue.AutoSize = true;
|
|
||||||
this.labelSetValue.Location = new System.Drawing.Point(29, 59);
|
|
||||||
this.labelSetValue.Name = "labelSetValue";
|
|
||||||
this.labelSetValue.Size = new System.Drawing.Size(61, 12);
|
|
||||||
this.labelSetValue.TabIndex = 1;
|
|
||||||
this.labelSetValue.Text = "Set value:";
|
|
||||||
//
|
|
||||||
// labelSetName
|
|
||||||
//
|
|
||||||
this.labelSetName.AutoSize = true;
|
|
||||||
this.labelSetName.Location = new System.Drawing.Point(29, 31);
|
|
||||||
this.labelSetName.Name = "labelSetName";
|
|
||||||
this.labelSetName.Size = new System.Drawing.Size(63, 12);
|
|
||||||
this.labelSetName.TabIndex = 0;
|
|
||||||
this.labelSetName.Text = "Set name:";
|
|
||||||
//
|
|
||||||
// gbImportAndExport
|
|
||||||
//
|
|
||||||
this.gbImportAndExport.Controls.Add(this.btnExport);
|
|
||||||
this.gbImportAndExport.Controls.Add(this.btnImport);
|
|
||||||
this.gbImportAndExport.Location = new System.Drawing.Point(12, 423);
|
|
||||||
this.gbImportAndExport.Name = "gbImportAndExport";
|
|
||||||
this.gbImportAndExport.Size = new System.Drawing.Size(419, 89);
|
|
||||||
this.gbImportAndExport.TabIndex = 2;
|
|
||||||
this.gbImportAndExport.TabStop = false;
|
|
||||||
this.gbImportAndExport.Text = "Import and export";
|
|
||||||
//
|
|
||||||
// btnExport
|
|
||||||
//
|
|
||||||
this.btnExport.Image = global::WelsonJS.Launcher.Properties.Resources.icon_export_32;
|
|
||||||
this.btnExport.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
|
||||||
this.btnExport.Location = new System.Drawing.Point(213, 29);
|
|
||||||
this.btnExport.Name = "btnExport";
|
|
||||||
this.btnExport.Padding = new System.Windows.Forms.Padding(11, 0, 0, 0);
|
|
||||||
this.btnExport.Size = new System.Drawing.Size(176, 40);
|
|
||||||
this.btnExport.TabIndex = 6;
|
|
||||||
this.btnExport.Text = "Export";
|
|
||||||
this.btnExport.UseVisualStyleBackColor = true;
|
|
||||||
this.btnExport.Click += new System.EventHandler(this.btnExport_Click);
|
|
||||||
//
|
|
||||||
// btnImport
|
|
||||||
//
|
|
||||||
this.btnImport.Image = global::WelsonJS.Launcher.Properties.Resources.icon_import_32;
|
|
||||||
this.btnImport.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
|
||||||
this.btnImport.Location = new System.Drawing.Point(31, 29);
|
|
||||||
this.btnImport.Name = "btnImport";
|
|
||||||
this.btnImport.Padding = new System.Windows.Forms.Padding(11, 0, 0, 0);
|
|
||||||
this.btnImport.Size = new System.Drawing.Size(176, 40);
|
|
||||||
this.btnImport.TabIndex = 5;
|
|
||||||
this.btnImport.Text = "Import";
|
|
||||||
this.btnImport.UseVisualStyleBackColor = true;
|
|
||||||
this.btnImport.Click += new System.EventHandler(this.btnImport_Click);
|
|
||||||
//
|
|
||||||
// EnvForm
|
|
||||||
//
|
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
|
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
|
||||||
this.ClientSize = new System.Drawing.Size(447, 529);
|
|
||||||
this.Controls.Add(this.gbImportAndExport);
|
|
||||||
this.Controls.Add(this.gbUpdateUserDefinedVariable);
|
|
||||||
this.Controls.Add(this.gbUserDefinedVariables);
|
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
|
||||||
this.Icon = global::WelsonJS.Launcher.Properties.Resources.favicon;
|
|
||||||
this.MaximizeBox = false;
|
|
||||||
this.Name = "EnvForm";
|
|
||||||
this.Text = "User-defined variables editor";
|
|
||||||
this.gbUserDefinedVariables.ResumeLayout(false);
|
|
||||||
this.gbUpdateUserDefinedVariable.ResumeLayout(false);
|
|
||||||
this.gbUpdateUserDefinedVariable.PerformLayout();
|
|
||||||
this.gbImportAndExport.ResumeLayout(false);
|
|
||||||
this.ResumeLayout(false);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private System.Windows.Forms.GroupBox gbUserDefinedVariables;
|
|
||||||
private System.Windows.Forms.GroupBox gbUpdateUserDefinedVariable;
|
|
||||||
private System.Windows.Forms.TextBox textSetValue;
|
|
||||||
private System.Windows.Forms.TextBox textSetName;
|
|
||||||
private System.Windows.Forms.Label labelSetValue;
|
|
||||||
private System.Windows.Forms.Label labelSetName;
|
|
||||||
private System.Windows.Forms.Button btnOk;
|
|
||||||
private System.Windows.Forms.Button btnOpenFile;
|
|
||||||
private System.Windows.Forms.Button btnOpenDirectory;
|
|
||||||
private System.Windows.Forms.CheckBox checkDeleteVariable;
|
|
||||||
private System.Windows.Forms.ListView lvUserDefinedVariables;
|
|
||||||
private System.Windows.Forms.ColumnHeader columnHeader1;
|
|
||||||
private System.Windows.Forms.ColumnHeader columnHeader2;
|
|
||||||
private System.Windows.Forms.GroupBox gbImportAndExport;
|
|
||||||
private System.Windows.Forms.Button btnImport;
|
|
||||||
private System.Windows.Forms.Button btnExport;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,295 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
|
|
||||||
namespace WelsonJS.Launcher
|
|
||||||
{
|
|
||||||
public partial class EnvForm : Form
|
|
||||||
{
|
|
||||||
private Dictionary<string, string> userVariables = new Dictionary<string, string>();
|
|
||||||
private string tempFilePath;
|
|
||||||
private readonly Encoding defaultEncoding = Encoding.UTF8;
|
|
||||||
|
|
||||||
public EnvForm()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
InitializeListView();
|
|
||||||
|
|
||||||
// Set the variable file path
|
|
||||||
tempFilePath = Path.Combine(Program.GetAppDataPath(), "welsonjs_default.env");
|
|
||||||
|
|
||||||
LoadUserVariables(); // Load variables
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize ListView
|
|
||||||
private void InitializeListView()
|
|
||||||
{
|
|
||||||
lvUserDefinedVariables.View = View.Details;
|
|
||||||
lvUserDefinedVariables.FullRowSelect = true;
|
|
||||||
lvUserDefinedVariables.Columns[0].Width = 150;
|
|
||||||
lvUserDefinedVariables.Columns[1].Width = 220;
|
|
||||||
lvUserDefinedVariables.SelectedIndexChanged += lvUserDefinedVariables_SelectedIndexChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load user-defined variables from the temporary folder in .env format
|
|
||||||
private void LoadUserVariables()
|
|
||||||
{
|
|
||||||
if (File.Exists(tempFilePath))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string fileContent = File.ReadAllText(tempFilePath);
|
|
||||||
// Split based on new line characters
|
|
||||||
string[] keyValuePairs = fileContent.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
|
|
||||||
userVariables = new Dictionary<string, string>();
|
|
||||||
|
|
||||||
foreach (string pair in keyValuePairs)
|
|
||||||
{
|
|
||||||
// Split by the first occurrence of '='
|
|
||||||
int indexOfEquals = pair.IndexOf('=');
|
|
||||||
if (indexOfEquals != -1)
|
|
||||||
{
|
|
||||||
string key = pair.Substring(0, indexOfEquals).Trim();
|
|
||||||
string value = pair.Substring(indexOfEquals + 1).Trim();
|
|
||||||
|
|
||||||
// Remove surrounding quotes if present
|
|
||||||
if (value.StartsWith("\"") && value.EndsWith("\""))
|
|
||||||
{
|
|
||||||
value = value.Substring(1, value.Length - 2); // Remove the first and last character
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unescape double quotes in the value
|
|
||||||
value = value.Replace("\\\"", "\"");
|
|
||||||
|
|
||||||
userVariables[key] = value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MessageBox.Show($"Error parsing line: '{pair}'.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
MessageBox.Show($"Error loading variable file: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
||||||
userVariables = new Dictionary<string, string>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
userVariables = new Dictionary<string, string>();
|
|
||||||
}
|
|
||||||
UpdateListView();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update ListView with current variables
|
|
||||||
private void UpdateListView()
|
|
||||||
{
|
|
||||||
lvUserDefinedVariables.Items.Clear();
|
|
||||||
foreach (var variable in userVariables)
|
|
||||||
{
|
|
||||||
var item = new ListViewItem(variable.Key);
|
|
||||||
item.SubItems.Add(variable.Value);
|
|
||||||
lvUserDefinedVariables.Items.Add(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle ListView selection change
|
|
||||||
private void lvUserDefinedVariables_SelectedIndexChanged(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (lvUserDefinedVariables.SelectedItems.Count > 0)
|
|
||||||
{
|
|
||||||
var selectedItem = lvUserDefinedVariables.SelectedItems[0];
|
|
||||||
textSetName.Text = selectedItem.Text;
|
|
||||||
textSetValue.Text = selectedItem.SubItems[1].Text;
|
|
||||||
checkDeleteVariable.Checked = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle OK button click
|
|
||||||
private void btnOk_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
var name = textSetName.Text.Trim();
|
|
||||||
var value = textSetValue.Text.Trim();
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(name))
|
|
||||||
{
|
|
||||||
MessageBox.Show("Please enter a variable name.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (checkDeleteVariable.Checked)
|
|
||||||
{
|
|
||||||
if (userVariables.ContainsKey(name))
|
|
||||||
{
|
|
||||||
userVariables.Remove(name);
|
|
||||||
MessageBox.Show("Variable deleted.", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MessageBox.Show("Variable not found.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
userVariables[name] = value;
|
|
||||||
MessageBox.Show("Variable saved.", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateListView();
|
|
||||||
SaveUserVariables(); // Save variables
|
|
||||||
ClearInputFields();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save user-defined variables to the temporary folder in .env format
|
|
||||||
private void SaveUserVariables()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
List<string> lines = new List<string>();
|
|
||||||
|
|
||||||
foreach (var variable in userVariables)
|
|
||||||
{
|
|
||||||
// Escape double quotes in the value
|
|
||||||
string value = variable.Value.Replace("\"", "\\\"");
|
|
||||||
|
|
||||||
// Enclose the value in double quotes if it contains spaces
|
|
||||||
if (value.Contains(" "))
|
|
||||||
{
|
|
||||||
value = $"\"{value}\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the line in the format: KEY=VALUE
|
|
||||||
string line = $"{variable.Key}={value}";
|
|
||||||
lines.Add(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write lines to the file
|
|
||||||
File.WriteAllLines(tempFilePath, lines, defaultEncoding);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
MessageBox.Show($"Error saving variable file: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear input fields
|
|
||||||
private void ClearInputFields()
|
|
||||||
{
|
|
||||||
textSetName.Clear();
|
|
||||||
textSetValue.Clear();
|
|
||||||
checkDeleteVariable.Checked = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle "Open Directory" button click
|
|
||||||
private void btnOpenDirectory_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
using (var folderDialog = new FolderBrowserDialog())
|
|
||||||
{
|
|
||||||
if (folderDialog.ShowDialog() == DialogResult.OK)
|
|
||||||
{
|
|
||||||
textSetValue.Text = folderDialog.SelectedPath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle "Open File" button click
|
|
||||||
private void btnOpenFile_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
using (var fileDialog = new OpenFileDialog())
|
|
||||||
{
|
|
||||||
if (fileDialog.ShowDialog() == DialogResult.OK)
|
|
||||||
{
|
|
||||||
textSetName.Text = Path.GetFileName(fileDialog.FileName);
|
|
||||||
textSetValue.Text = fileDialog.FileName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void btnImport_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
using (var openFileDialog = new OpenFileDialog())
|
|
||||||
{
|
|
||||||
openFileDialog.Filter = "Env files (*.env)|*.env|All files (*.*)|*.*";
|
|
||||||
if (openFileDialog.ShowDialog() == DialogResult.OK)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Load variables from the selected file
|
|
||||||
string filePath = openFileDialog.FileName;
|
|
||||||
string[] lines = File.ReadAllLines(filePath, defaultEncoding);
|
|
||||||
|
|
||||||
foreach (string line in lines)
|
|
||||||
{
|
|
||||||
// Skip empty lines
|
|
||||||
if (string.IsNullOrWhiteSpace(line)) continue;
|
|
||||||
|
|
||||||
int indexOfEquals = line.IndexOf('=');
|
|
||||||
if (indexOfEquals != -1)
|
|
||||||
{
|
|
||||||
string key = line.Substring(0, indexOfEquals).Trim();
|
|
||||||
string value = line.Substring(indexOfEquals + 1).Trim();
|
|
||||||
|
|
||||||
// Remove surrounding quotes if present
|
|
||||||
if (value.StartsWith("\"") && value.EndsWith("\""))
|
|
||||||
{
|
|
||||||
value = value.Substring(1, value.Length - 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unescape double quotes in the value
|
|
||||||
value = value.Replace("\\\"", "\"");
|
|
||||||
|
|
||||||
// Update or add the key-value pair
|
|
||||||
userVariables[key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the updated variables to the file
|
|
||||||
SaveUserVariables();
|
|
||||||
UpdateListView(); // Refresh the display
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
MessageBox.Show($"Error importing variable file: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void btnExport_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
SaveFileDialog saveFileDialog = new SaveFileDialog();
|
|
||||||
saveFileDialog.Filter = "Env files (*.env)|*.env|All files (*.*)|*.*";
|
|
||||||
if (saveFileDialog.ShowDialog() == DialogResult.OK)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Save the current variables to the selected file
|
|
||||||
string filePath = saveFileDialog.FileName;
|
|
||||||
List<string> lines = new List<string>();
|
|
||||||
foreach (var variable in userVariables)
|
|
||||||
{
|
|
||||||
// Escape double quotes in the value
|
|
||||||
string value = variable.Value.Replace("\"", "\\\"");
|
|
||||||
|
|
||||||
// Enclose the value in double quotes if it contains spaces
|
|
||||||
if (value.Contains(" "))
|
|
||||||
{
|
|
||||||
value = $"\"{value}\"";
|
|
||||||
}
|
|
||||||
|
|
||||||
lines.Add($"{variable.Key}={value}");
|
|
||||||
}
|
|
||||||
File.WriteAllLines(filePath, lines, defaultEncoding);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
MessageBox.Show($"Error exporting variable file: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,120 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<root>
|
|
||||||
<!--
|
|
||||||
Microsoft ResX Schema
|
|
||||||
|
|
||||||
Version 2.0
|
|
||||||
|
|
||||||
The primary goals of this format is to allow a simple XML format
|
|
||||||
that is mostly human readable. The generation and parsing of the
|
|
||||||
various data types are done through the TypeConverter classes
|
|
||||||
associated with the data types.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
... ado.net/XML headers & schema ...
|
|
||||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
|
||||||
<resheader name="version">2.0</resheader>
|
|
||||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
|
||||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
|
||||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
|
||||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
|
||||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
|
||||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
|
||||||
</data>
|
|
||||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
|
||||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
|
||||||
<comment>This is a comment</comment>
|
|
||||||
</data>
|
|
||||||
|
|
||||||
There are any number of "resheader" rows that contain simple
|
|
||||||
name/value pairs.
|
|
||||||
|
|
||||||
Each data row contains a name, and value. The row also contains a
|
|
||||||
type or mimetype. Type corresponds to a .NET class that support
|
|
||||||
text/value conversion through the TypeConverter architecture.
|
|
||||||
Classes that don't support this are serialized and stored with the
|
|
||||||
mimetype set.
|
|
||||||
|
|
||||||
The mimetype is used for serialized objects, and tells the
|
|
||||||
ResXResourceReader how to depersist the object. This is currently not
|
|
||||||
extensible. For a given mimetype the value must be set accordingly:
|
|
||||||
|
|
||||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
|
||||||
that the ResXResourceWriter will generate, however the reader can
|
|
||||||
read any of the formats listed below.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.binary.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.soap.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
|
||||||
value : The object must be serialized into a byte array
|
|
||||||
: using a System.ComponentModel.TypeConverter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
-->
|
|
||||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
|
||||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
|
||||||
<xsd:element name="root" msdata:IsDataSet="true">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:choice maxOccurs="unbounded">
|
|
||||||
<xsd:element name="metadata">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
|
||||||
<xsd:attribute ref="xml:space" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="assembly">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:attribute name="alias" type="xsd:string" />
|
|
||||||
<xsd:attribute name="name" type="xsd:string" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="data">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
|
||||||
<xsd:attribute ref="xml:space" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="resheader">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:choice>
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:schema>
|
|
||||||
<resheader name="resmimetype">
|
|
||||||
<value>text/microsoft-resx</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="version">
|
|
||||||
<value>2.0</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="reader">
|
|
||||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="writer">
|
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
</root>
|
|
|
@ -1,89 +0,0 @@
|
||||||
namespace WelsonJS.Launcher
|
|
||||||
{
|
|
||||||
partial class GlobalSettingsForm
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Required designer variable.
|
|
||||||
/// </summary>
|
|
||||||
private System.ComponentModel.IContainer components = null;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Clean up any resources being used.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing && (components != null))
|
|
||||||
{
|
|
||||||
components.Dispose();
|
|
||||||
}
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Windows Form Designer generated code
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Required method for Designer support - do not modify
|
|
||||||
/// the contents of this method with the code editor.
|
|
||||||
/// </summary>
|
|
||||||
private void InitializeComponent()
|
|
||||||
{
|
|
||||||
this.gbMaxScriptStatements = new System.Windows.Forms.GroupBox();
|
|
||||||
this.btnOkMaxScriptStatements = new System.Windows.Forms.Button();
|
|
||||||
this.txtMaxScriptStatements = new System.Windows.Forms.TextBox();
|
|
||||||
this.gbMaxScriptStatements.SuspendLayout();
|
|
||||||
this.SuspendLayout();
|
|
||||||
//
|
|
||||||
// gbMaxScriptStatements
|
|
||||||
//
|
|
||||||
this.gbMaxScriptStatements.Controls.Add(this.btnOkMaxScriptStatements);
|
|
||||||
this.gbMaxScriptStatements.Controls.Add(this.txtMaxScriptStatements);
|
|
||||||
this.gbMaxScriptStatements.Location = new System.Drawing.Point(12, 12);
|
|
||||||
this.gbMaxScriptStatements.Name = "gbMaxScriptStatements";
|
|
||||||
this.gbMaxScriptStatements.Size = new System.Drawing.Size(290, 67);
|
|
||||||
this.gbMaxScriptStatements.TabIndex = 0;
|
|
||||||
this.gbMaxScriptStatements.TabStop = false;
|
|
||||||
this.gbMaxScriptStatements.Text = "MaxScriptStatements (GUI only)";
|
|
||||||
//
|
|
||||||
// btnOkMaxScriptStatements
|
|
||||||
//
|
|
||||||
this.btnOkMaxScriptStatements.Location = new System.Drawing.Point(218, 30);
|
|
||||||
this.btnOkMaxScriptStatements.Name = "btnOkMaxScriptStatements";
|
|
||||||
this.btnOkMaxScriptStatements.Size = new System.Drawing.Size(57, 21);
|
|
||||||
this.btnOkMaxScriptStatements.TabIndex = 1;
|
|
||||||
this.btnOkMaxScriptStatements.Text = "Ok";
|
|
||||||
this.btnOkMaxScriptStatements.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
|
|
||||||
this.btnOkMaxScriptStatements.UseVisualStyleBackColor = true;
|
|
||||||
this.btnOkMaxScriptStatements.Click += new System.EventHandler(this.btnOkMaxScriptStatements_Click);
|
|
||||||
//
|
|
||||||
// txtMaxScriptStatements
|
|
||||||
//
|
|
||||||
this.txtMaxScriptStatements.Location = new System.Drawing.Point(15, 30);
|
|
||||||
this.txtMaxScriptStatements.Name = "txtMaxScriptStatements";
|
|
||||||
this.txtMaxScriptStatements.Size = new System.Drawing.Size(197, 21);
|
|
||||||
this.txtMaxScriptStatements.TabIndex = 1;
|
|
||||||
//
|
|
||||||
// GlobalSettingsForm
|
|
||||||
//
|
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
|
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
|
||||||
this.ClientSize = new System.Drawing.Size(315, 92);
|
|
||||||
this.Controls.Add(this.gbMaxScriptStatements);
|
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
|
||||||
this.Icon = global::WelsonJS.Launcher.Properties.Resources.favicon;
|
|
||||||
this.MaximizeBox = false;
|
|
||||||
this.Name = "GlobalSettingsForm";
|
|
||||||
this.Text = "Global settings...";
|
|
||||||
this.gbMaxScriptStatements.ResumeLayout(false);
|
|
||||||
this.gbMaxScriptStatements.PerformLayout();
|
|
||||||
this.ResumeLayout(false);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private System.Windows.Forms.GroupBox gbMaxScriptStatements;
|
|
||||||
private System.Windows.Forms.TextBox txtMaxScriptStatements;
|
|
||||||
private System.Windows.Forms.Button btnOkMaxScriptStatements;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
using Microsoft.Win32;
|
|
||||||
using System;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
|
|
||||||
namespace WelsonJS.Launcher
|
|
||||||
{
|
|
||||||
public partial class GlobalSettingsForm : Form
|
|
||||||
{
|
|
||||||
private const string RegistryPath = "Software\\Microsoft\\Internet Explorer\\Styles";
|
|
||||||
private const string RegistryKey = "MaxScriptStatements";
|
|
||||||
|
|
||||||
public GlobalSettingsForm()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
LoadRegistryValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LoadRegistryValue()
|
|
||||||
{
|
|
||||||
using (RegistryKey key = Registry.CurrentUser.OpenSubKey(RegistryPath))
|
|
||||||
{
|
|
||||||
if (key != null)
|
|
||||||
{
|
|
||||||
string value = key.GetValue(RegistryKey)?.ToString();
|
|
||||||
if (value != null && int.TryParse(value, out int maxStatements))
|
|
||||||
{
|
|
||||||
txtMaxScriptStatements.Text = maxStatements.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void btnOkMaxScriptStatements_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (int.TryParse(txtMaxScriptStatements.Text, out int maxStatements))
|
|
||||||
{
|
|
||||||
using (RegistryKey key = Registry.CurrentUser.CreateSubKey(RegistryPath))
|
|
||||||
{
|
|
||||||
key.SetValue(RegistryKey, maxStatements, RegistryValueKind.DWord);
|
|
||||||
}
|
|
||||||
MessageBox.Show($"MaxScriptStatements setting has been changed to {maxStatements}.", "Confirmation", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MessageBox.Show("Please enter a valid number within the DWORD range.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
MessageBox.Show($"An error occurred while trying to change the MaxScriptStatements setting: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,120 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<root>
|
|
||||||
<!--
|
|
||||||
Microsoft ResX Schema
|
|
||||||
|
|
||||||
Version 2.0
|
|
||||||
|
|
||||||
The primary goals of this format is to allow a simple XML format
|
|
||||||
that is mostly human readable. The generation and parsing of the
|
|
||||||
various data types are done through the TypeConverter classes
|
|
||||||
associated with the data types.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
... ado.net/XML headers & schema ...
|
|
||||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
|
||||||
<resheader name="version">2.0</resheader>
|
|
||||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
|
||||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
|
||||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
|
||||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
|
||||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
|
||||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
|
||||||
</data>
|
|
||||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
|
||||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
|
||||||
<comment>This is a comment</comment>
|
|
||||||
</data>
|
|
||||||
|
|
||||||
There are any number of "resheader" rows that contain simple
|
|
||||||
name/value pairs.
|
|
||||||
|
|
||||||
Each data row contains a name, and value. The row also contains a
|
|
||||||
type or mimetype. Type corresponds to a .NET class that support
|
|
||||||
text/value conversion through the TypeConverter architecture.
|
|
||||||
Classes that don't support this are serialized and stored with the
|
|
||||||
mimetype set.
|
|
||||||
|
|
||||||
The mimetype is used for serialized objects, and tells the
|
|
||||||
ResXResourceReader how to depersist the object. This is currently not
|
|
||||||
extensible. For a given mimetype the value must be set accordingly:
|
|
||||||
|
|
||||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
|
||||||
that the ResXResourceWriter will generate, however the reader can
|
|
||||||
read any of the formats listed below.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.binary.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.soap.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
|
||||||
value : The object must be serialized into a byte array
|
|
||||||
: using a System.ComponentModel.TypeConverter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
-->
|
|
||||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
|
||||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
|
||||||
<xsd:element name="root" msdata:IsDataSet="true">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:choice maxOccurs="unbounded">
|
|
||||||
<xsd:element name="metadata">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
|
||||||
<xsd:attribute ref="xml:space" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="assembly">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:attribute name="alias" type="xsd:string" />
|
|
||||||
<xsd:attribute name="name" type="xsd:string" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="data">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
|
||||||
<xsd:attribute ref="xml:space" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="resheader">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:choice>
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:schema>
|
|
||||||
<resheader name="resmimetype">
|
|
||||||
<value>text/microsoft-resx</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="version">
|
|
||||||
<value>2.0</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="reader">
|
|
||||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="writer">
|
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
</root>
|
|
|
@ -1,25 +0,0 @@
|
||||||
using System.Net;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace WelsonJS.Launcher
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Defines a contract for resource tools that can handle specific HTTP requests.
|
|
||||||
/// </summary>
|
|
||||||
public interface IResourceTool
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Determines whether this tool can handle the specified path.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The request path to check.</param>
|
|
||||||
/// <returns>True if this tool can handle the request; otherwise, false.</returns>
|
|
||||||
bool CanHandle(string path);
|
|
||||||
/// <summary>
|
|
||||||
/// Asynchronously processes the HTTP request for the specified path.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="context">The HTTP listener context containing request and response objects.</param>
|
|
||||||
/// <param name="path">The request path to handle.</param>
|
|
||||||
/// <returns>A task representing the asynchronous operation.</returns>
|
|
||||||
Task HandleAsync(HttpListenerContext context, string path);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,170 +0,0 @@
|
||||||
namespace WelsonJS.Launcher
|
|
||||||
{
|
|
||||||
partial class InstancesForm
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Required designer variable.
|
|
||||||
/// </summary>
|
|
||||||
private System.ComponentModel.IContainer components = null;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Clean up any resources being used.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
|
||||||
protected override void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (disposing && (components != null))
|
|
||||||
{
|
|
||||||
components.Dispose();
|
|
||||||
}
|
|
||||||
base.Dispose(disposing);
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Windows Form Designer generated code
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Required method for Designer support - do not modify
|
|
||||||
/// the contents of this method with the code editor.
|
|
||||||
/// </summary>
|
|
||||||
private void InitializeComponent()
|
|
||||||
{
|
|
||||||
this.lvInstances = new System.Windows.Forms.ListView();
|
|
||||||
this.chInstanceId = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
|
||||||
this.chFirstDeployTime = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
|
||||||
this.btnDelete = new System.Windows.Forms.Button();
|
|
||||||
this.btnOpenWithExplorer = new System.Windows.Forms.Button();
|
|
||||||
this.cbInteractiveServiceApp = new System.Windows.Forms.CheckBox();
|
|
||||||
this.txtUseSpecificScript = new System.Windows.Forms.TextBox();
|
|
||||||
this.cbUseSpecificScript = new System.Windows.Forms.CheckBox();
|
|
||||||
this.btnStart = new System.Windows.Forms.Button();
|
|
||||||
this.SuspendLayout();
|
|
||||||
//
|
|
||||||
// lvInstances
|
|
||||||
//
|
|
||||||
this.lvInstances.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
|
|
||||||
this.chInstanceId,
|
|
||||||
this.chFirstDeployTime});
|
|
||||||
this.lvInstances.HideSelection = false;
|
|
||||||
this.lvInstances.Location = new System.Drawing.Point(8, 8);
|
|
||||||
this.lvInstances.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
|
||||||
this.lvInstances.Name = "lvInstances";
|
|
||||||
this.lvInstances.Size = new System.Drawing.Size(384, 170);
|
|
||||||
this.lvInstances.TabIndex = 0;
|
|
||||||
this.lvInstances.UseCompatibleStateImageBehavior = false;
|
|
||||||
this.lvInstances.View = System.Windows.Forms.View.Details;
|
|
||||||
//
|
|
||||||
// chInstanceId
|
|
||||||
//
|
|
||||||
this.chInstanceId.Text = "Instance ID";
|
|
||||||
this.chInstanceId.Width = 220;
|
|
||||||
//
|
|
||||||
// chFirstDeployTime
|
|
||||||
//
|
|
||||||
this.chFirstDeployTime.Text = "First Deploy Time";
|
|
||||||
this.chFirstDeployTime.Width = 160;
|
|
||||||
//
|
|
||||||
// btnDelete
|
|
||||||
//
|
|
||||||
this.btnDelete.Image = global::WelsonJS.Launcher.Properties.Resources.icon_delete_32;
|
|
||||||
this.btnDelete.Location = new System.Drawing.Point(120, 243);
|
|
||||||
this.btnDelete.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
|
||||||
this.btnDelete.Name = "btnDelete";
|
|
||||||
this.btnDelete.Size = new System.Drawing.Size(105, 40);
|
|
||||||
this.btnDelete.TabIndex = 2;
|
|
||||||
this.btnDelete.Text = "Delete";
|
|
||||||
this.btnDelete.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
|
|
||||||
this.btnDelete.UseVisualStyleBackColor = true;
|
|
||||||
this.btnDelete.Click += new System.EventHandler(this.btnDelete_Click);
|
|
||||||
//
|
|
||||||
// btnOpenWithExplorer
|
|
||||||
//
|
|
||||||
this.btnOpenWithExplorer.Image = global::WelsonJS.Launcher.Properties.Resources.icon_directory_32;
|
|
||||||
this.btnOpenWithExplorer.Location = new System.Drawing.Point(229, 243);
|
|
||||||
this.btnOpenWithExplorer.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
|
||||||
this.btnOpenWithExplorer.Name = "btnOpenWithExplorer";
|
|
||||||
this.btnOpenWithExplorer.Size = new System.Drawing.Size(162, 40);
|
|
||||||
this.btnOpenWithExplorer.TabIndex = 3;
|
|
||||||
this.btnOpenWithExplorer.Text = "Open with Explorer";
|
|
||||||
this.btnOpenWithExplorer.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
|
|
||||||
this.btnOpenWithExplorer.UseVisualStyleBackColor = true;
|
|
||||||
this.btnOpenWithExplorer.Click += new System.EventHandler(this.btnOpenWithExplorer_Click);
|
|
||||||
//
|
|
||||||
// cbInteractiveServiceApp
|
|
||||||
//
|
|
||||||
this.cbInteractiveServiceApp.AutoSize = true;
|
|
||||||
this.cbInteractiveServiceApp.Location = new System.Drawing.Point(10, 215);
|
|
||||||
this.cbInteractiveServiceApp.Name = "cbInteractiveServiceApp";
|
|
||||||
this.cbInteractiveServiceApp.Size = new System.Drawing.Size(254, 16);
|
|
||||||
this.cbInteractiveServiceApp.TabIndex = 9;
|
|
||||||
this.cbInteractiveServiceApp.Text = "This is an Interactive Service Application";
|
|
||||||
this.cbInteractiveServiceApp.UseVisualStyleBackColor = true;
|
|
||||||
//
|
|
||||||
// txtUseSpecificScript
|
|
||||||
//
|
|
||||||
this.txtUseSpecificScript.Enabled = false;
|
|
||||||
this.txtUseSpecificScript.Location = new System.Drawing.Point(199, 189);
|
|
||||||
this.txtUseSpecificScript.Name = "txtUseSpecificScript";
|
|
||||||
this.txtUseSpecificScript.Size = new System.Drawing.Size(110, 21);
|
|
||||||
this.txtUseSpecificScript.TabIndex = 8;
|
|
||||||
//
|
|
||||||
// cbUseSpecificScript
|
|
||||||
//
|
|
||||||
this.cbUseSpecificScript.AutoSize = true;
|
|
||||||
this.cbUseSpecificScript.Location = new System.Drawing.Point(10, 192);
|
|
||||||
this.cbUseSpecificScript.Name = "cbUseSpecificScript";
|
|
||||||
this.cbUseSpecificScript.Size = new System.Drawing.Size(184, 16);
|
|
||||||
this.cbUseSpecificScript.TabIndex = 7;
|
|
||||||
this.cbUseSpecificScript.Text = "I want to use specific script ";
|
|
||||||
this.cbUseSpecificScript.UseVisualStyleBackColor = true;
|
|
||||||
this.cbUseSpecificScript.CheckedChanged += new System.EventHandler(this.cbUseSpecificScript_CheckedChanged);
|
|
||||||
//
|
|
||||||
// btnStart
|
|
||||||
//
|
|
||||||
this.btnStart.Image = global::WelsonJS.Launcher.Properties.Resources.icon_start_32;
|
|
||||||
this.btnStart.Location = new System.Drawing.Point(10, 243);
|
|
||||||
this.btnStart.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
|
||||||
this.btnStart.Name = "btnStart";
|
|
||||||
this.btnStart.Size = new System.Drawing.Size(105, 40);
|
|
||||||
this.btnStart.TabIndex = 1;
|
|
||||||
this.btnStart.Text = "Start";
|
|
||||||
this.btnStart.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
|
|
||||||
this.btnStart.UseVisualStyleBackColor = true;
|
|
||||||
this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
|
|
||||||
//
|
|
||||||
// InstancesForm
|
|
||||||
//
|
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
|
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
|
||||||
this.ClientSize = new System.Drawing.Size(401, 296);
|
|
||||||
this.Controls.Add(this.btnStart);
|
|
||||||
this.Controls.Add(this.lvInstances);
|
|
||||||
this.Controls.Add(this.btnDelete);
|
|
||||||
this.Controls.Add(this.cbUseSpecificScript);
|
|
||||||
this.Controls.Add(this.cbInteractiveServiceApp);
|
|
||||||
this.Controls.Add(this.btnOpenWithExplorer);
|
|
||||||
this.Controls.Add(this.txtUseSpecificScript);
|
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
|
||||||
this.Icon = global::WelsonJS.Launcher.Properties.Resources.favicon;
|
|
||||||
this.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
|
||||||
this.MaximizeBox = false;
|
|
||||||
this.Name = "InstancesForm";
|
|
||||||
this.Text = "Instances";
|
|
||||||
this.Load += new System.EventHandler(this.InstancesForm_Load);
|
|
||||||
this.ResumeLayout(false);
|
|
||||||
this.PerformLayout();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private System.Windows.Forms.ListView lvInstances;
|
|
||||||
private System.Windows.Forms.Button btnDelete;
|
|
||||||
private System.Windows.Forms.Button btnOpenWithExplorer;
|
|
||||||
private System.Windows.Forms.CheckBox cbInteractiveServiceApp;
|
|
||||||
private System.Windows.Forms.TextBox txtUseSpecificScript;
|
|
||||||
private System.Windows.Forms.CheckBox cbUseSpecificScript;
|
|
||||||
private System.Windows.Forms.ColumnHeader chInstanceId;
|
|
||||||
private System.Windows.Forms.ColumnHeader chFirstDeployTime;
|
|
||||||
private System.Windows.Forms.Button btnStart;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,141 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
|
|
||||||
namespace WelsonJS.Launcher
|
|
||||||
{
|
|
||||||
public partial class InstancesForm : Form
|
|
||||||
{
|
|
||||||
private string entryFileName;
|
|
||||||
private string scriptName;
|
|
||||||
private const string timestampFormat = "yyyy-MM-dd HH:mm:ss";
|
|
||||||
|
|
||||||
public InstancesForm()
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
|
|
||||||
entryFileName = "bootstrap.bat";
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InstancesForm_Load(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
lvInstances.Items.Clear();
|
|
||||||
LoadInstances(Program.GetAppDataPath());
|
|
||||||
LoadInstances(Path.GetTempPath());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LoadInstances(string instancesRoot)
|
|
||||||
{
|
|
||||||
if (!Directory.Exists(instancesRoot))
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (string dir in Directory.GetDirectories(instancesRoot))
|
|
||||||
{
|
|
||||||
string timestampFile = Path.Combine(dir, ".welsonjs_first_deploy_time");
|
|
||||||
string entryScriptFile = Path.Combine(dir, "app.js");
|
|
||||||
string firstDeployTime = null;
|
|
||||||
|
|
||||||
if (File.Exists(timestampFile)
|
|
||||||
&& DateTime.TryParse(File.ReadAllText(timestampFile).Trim(), out DateTime parsedTimestamp))
|
|
||||||
{
|
|
||||||
firstDeployTime = parsedTimestamp.ToString(timestampFormat);
|
|
||||||
}
|
|
||||||
else if (File.Exists(entryScriptFile))
|
|
||||||
{
|
|
||||||
firstDeployTime = File.GetCreationTime(entryScriptFile).ToString(timestampFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (firstDeployTime != null)
|
|
||||||
{
|
|
||||||
lvInstances.Items.Add(new ListViewItem(new[]
|
|
||||||
{
|
|
||||||
Path.GetFileName(dir),
|
|
||||||
firstDeployTime
|
|
||||||
})
|
|
||||||
{
|
|
||||||
Tag = dir
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void btnStart_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (lvInstances.SelectedItems.Count > 0)
|
|
||||||
{
|
|
||||||
scriptName = txtUseSpecificScript.Text;
|
|
||||||
|
|
||||||
string instanceId = lvInstances.SelectedItems[0].Text;
|
|
||||||
string workingDirectory = Program.GetWorkingDirectory(instanceId, true);
|
|
||||||
|
|
||||||
Task.Run(() =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Run the appliction
|
|
||||||
Program.RunCommandPrompt(workingDirectory, entryFileName, scriptName, cbUseSpecificScript.Checked, cbInteractiveServiceApp.Checked);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
MessageBox.Show(ex.Message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MessageBox.Show("No selected an instance");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void btnDelete_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (lvInstances.SelectedItems.Count > 0)
|
|
||||||
{
|
|
||||||
string instanceId = lvInstances.SelectedItems[0].Text;
|
|
||||||
string workingDirectory = Program.GetWorkingDirectory(instanceId, false);
|
|
||||||
|
|
||||||
if (!Directory.Exists(workingDirectory))
|
|
||||||
{
|
|
||||||
workingDirectory = Path.Combine(Path.GetTempPath(), instanceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Directory.Exists(workingDirectory))
|
|
||||||
{
|
|
||||||
Directory.Delete(workingDirectory, true);
|
|
||||||
|
|
||||||
lvInstances.Items.Clear();
|
|
||||||
LoadInstances(Program.GetAppDataPath());
|
|
||||||
LoadInstances(Path.GetTempPath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MessageBox.Show("No selected an instance");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void btnOpenWithExplorer_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (lvInstances.SelectedItems.Count > 0)
|
|
||||||
{
|
|
||||||
string instanceId = lvInstances.SelectedItems[0].Text;
|
|
||||||
string workingDirectory = Program.GetWorkingDirectory(instanceId, true);
|
|
||||||
|
|
||||||
if (Directory.Exists(workingDirectory))
|
|
||||||
{
|
|
||||||
System.Diagnostics.Process.Start("explorer", workingDirectory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MessageBox.Show("No selected an instance");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void cbUseSpecificScript_CheckedChanged(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
txtUseSpecificScript.Enabled = cbUseSpecificScript.Checked;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,120 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<root>
|
|
||||||
<!--
|
|
||||||
Microsoft ResX Schema
|
|
||||||
|
|
||||||
Version 2.0
|
|
||||||
|
|
||||||
The primary goals of this format is to allow a simple XML format
|
|
||||||
that is mostly human readable. The generation and parsing of the
|
|
||||||
various data types are done through the TypeConverter classes
|
|
||||||
associated with the data types.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
... ado.net/XML headers & schema ...
|
|
||||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
|
||||||
<resheader name="version">2.0</resheader>
|
|
||||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
|
||||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
|
||||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
|
||||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
|
||||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
|
||||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
|
||||||
</data>
|
|
||||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
|
||||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
|
||||||
<comment>This is a comment</comment>
|
|
||||||
</data>
|
|
||||||
|
|
||||||
There are any number of "resheader" rows that contain simple
|
|
||||||
name/value pairs.
|
|
||||||
|
|
||||||
Each data row contains a name, and value. The row also contains a
|
|
||||||
type or mimetype. Type corresponds to a .NET class that support
|
|
||||||
text/value conversion through the TypeConverter architecture.
|
|
||||||
Classes that don't support this are serialized and stored with the
|
|
||||||
mimetype set.
|
|
||||||
|
|
||||||
The mimetype is used for serialized objects, and tells the
|
|
||||||
ResXResourceReader how to depersist the object. This is currently not
|
|
||||||
extensible. For a given mimetype the value must be set accordingly:
|
|
||||||
|
|
||||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
|
||||||
that the ResXResourceWriter will generate, however the reader can
|
|
||||||
read any of the formats listed below.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.binary.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.soap.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
|
||||||
value : The object must be serialized into a byte array
|
|
||||||
: using a System.ComponentModel.TypeConverter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
-->
|
|
||||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
|
||||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
|
||||||
<xsd:element name="root" msdata:IsDataSet="true">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:choice maxOccurs="unbounded">
|
|
||||||
<xsd:element name="metadata">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
|
||||||
<xsd:attribute ref="xml:space" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="assembly">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:attribute name="alias" type="xsd:string" />
|
|
||||||
<xsd:attribute name="name" type="xsd:string" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="data">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
|
||||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
|
||||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
|
||||||
<xsd:attribute ref="xml:space" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
<xsd:element name="resheader">
|
|
||||||
<xsd:complexType>
|
|
||||||
<xsd:sequence>
|
|
||||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
|
||||||
</xsd:sequence>
|
|
||||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:choice>
|
|
||||||
</xsd:complexType>
|
|
||||||
</xsd:element>
|
|
||||||
</xsd:schema>
|
|
||||||
<resheader name="resmimetype">
|
|
||||||
<value>text/microsoft-resx</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="version">
|
|
||||||
<value>2.0</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="reader">
|
|
||||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
<resheader name="writer">
|
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
|
||||||
</resheader>
|
|
||||||
</root>
|
|
260
WelsonJS.Toolkit/WelsonJS.Launcher/MainForm.Designer.cs
generated
|
@ -28,59 +28,44 @@
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent()
|
private void InitializeComponent()
|
||||||
{
|
{
|
||||||
this.components = new System.ComponentModel.Container();
|
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
|
||||||
this.btnRunFromZipFile = new System.Windows.Forms.Button();
|
this.button1 = new System.Windows.Forms.Button();
|
||||||
this.btnRunFromExternalLink = new System.Windows.Forms.Button();
|
this.button2 = new System.Windows.Forms.Button();
|
||||||
this.label1 = new System.Windows.Forms.Label();
|
this.label1 = new System.Windows.Forms.Label();
|
||||||
this.linkLabel1 = new System.Windows.Forms.LinkLabel();
|
this.linkLabel1 = new System.Windows.Forms.LinkLabel();
|
||||||
this.cbUseSpecificScript = new System.Windows.Forms.CheckBox();
|
this.checkBox1 = new System.Windows.Forms.CheckBox();
|
||||||
this.txtUseSpecificScript = new System.Windows.Forms.TextBox();
|
this.textBox1 = new System.Windows.Forms.TextBox();
|
||||||
this.cbInteractiveServiceApp = new System.Windows.Forms.CheckBox();
|
this.checkBox2 = new System.Windows.Forms.CheckBox();
|
||||||
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
|
|
||||||
this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
this.userdefinedVariablesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
this.instancesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
this.runAsAdministratorToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
this.globalSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
this.startCodeEditorToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
this.openCopilotToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
this.notifyIcon1 = new System.Windows.Forms.NotifyIcon(this.components);
|
|
||||||
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
|
|
||||||
this.openLauncherToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
this.openCodeEditorToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
this.menuStrip1.SuspendLayout();
|
|
||||||
this.contextMenuStrip1.SuspendLayout();
|
|
||||||
this.SuspendLayout();
|
this.SuspendLayout();
|
||||||
//
|
//
|
||||||
// btnRunFromZipFile
|
// button1
|
||||||
//
|
//
|
||||||
this.btnRunFromZipFile.Image = global::WelsonJS.Launcher.Properties.Resources.icon_zip_128;
|
this.button1.Image = global::WelsonJS.Launcher.Properties.Resources.icon_zip_128;
|
||||||
this.btnRunFromZipFile.Location = new System.Drawing.Point(24, 67);
|
this.button1.Location = new System.Drawing.Point(24, 49);
|
||||||
this.btnRunFromZipFile.Name = "btnRunFromZipFile";
|
this.button1.Name = "button1";
|
||||||
this.btnRunFromZipFile.Size = new System.Drawing.Size(200, 200);
|
this.button1.Size = new System.Drawing.Size(200, 200);
|
||||||
this.btnRunFromZipFile.TabIndex = 0;
|
this.button1.TabIndex = 0;
|
||||||
this.btnRunFromZipFile.Text = "From ZIP file...";
|
this.button1.Text = "From ZIP file...";
|
||||||
this.btnRunFromZipFile.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
|
this.button1.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
|
||||||
this.btnRunFromZipFile.UseVisualStyleBackColor = true;
|
this.button1.UseVisualStyleBackColor = true;
|
||||||
this.btnRunFromZipFile.Click += new System.EventHandler(this.btnRunFromZipFile_Click);
|
this.button1.Click += new System.EventHandler(this.button1_Click);
|
||||||
//
|
//
|
||||||
// btnRunFromExternalLink
|
// button2
|
||||||
//
|
//
|
||||||
this.btnRunFromExternalLink.Image = global::WelsonJS.Launcher.Properties.Resources.icon_link_128;
|
this.button2.Image = global::WelsonJS.Launcher.Properties.Resources.icon_link_128;
|
||||||
this.btnRunFromExternalLink.Location = new System.Drawing.Point(230, 67);
|
this.button2.Location = new System.Drawing.Point(230, 49);
|
||||||
this.btnRunFromExternalLink.Name = "btnRunFromExternalLink";
|
this.button2.Name = "button2";
|
||||||
this.btnRunFromExternalLink.Size = new System.Drawing.Size(200, 200);
|
this.button2.Size = new System.Drawing.Size(200, 200);
|
||||||
this.btnRunFromExternalLink.TabIndex = 1;
|
this.button2.TabIndex = 1;
|
||||||
this.btnRunFromExternalLink.Text = "From external link...";
|
this.button2.Text = "From external link...";
|
||||||
this.btnRunFromExternalLink.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
|
this.button2.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
|
||||||
this.btnRunFromExternalLink.UseVisualStyleBackColor = true;
|
this.button2.UseVisualStyleBackColor = true;
|
||||||
this.btnRunFromExternalLink.Click += new System.EventHandler(this.btnRunFromExternalLink_Click);
|
this.button2.Click += new System.EventHandler(this.button2_Click);
|
||||||
//
|
//
|
||||||
// label1
|
// label1
|
||||||
//
|
//
|
||||||
this.label1.AutoSize = true;
|
this.label1.AutoSize = true;
|
||||||
this.label1.Location = new System.Drawing.Point(24, 41);
|
this.label1.Location = new System.Drawing.Point(24, 23);
|
||||||
this.label1.Name = "label1";
|
this.label1.Name = "label1";
|
||||||
this.label1.Size = new System.Drawing.Size(312, 12);
|
this.label1.Size = new System.Drawing.Size(312, 12);
|
||||||
this.label1.TabIndex = 2;
|
this.label1.TabIndex = 2;
|
||||||
|
@ -89,7 +74,7 @@
|
||||||
// linkLabel1
|
// linkLabel1
|
||||||
//
|
//
|
||||||
this.linkLabel1.AutoSize = true;
|
this.linkLabel1.AutoSize = true;
|
||||||
this.linkLabel1.Location = new System.Drawing.Point(24, 345);
|
this.linkLabel1.Location = new System.Drawing.Point(24, 327);
|
||||||
this.linkLabel1.Name = "linkLabel1";
|
this.linkLabel1.Name = "linkLabel1";
|
||||||
this.linkLabel1.Size = new System.Drawing.Size(219, 12);
|
this.linkLabel1.Size = new System.Drawing.Size(219, 12);
|
||||||
this.linkLabel1.TabIndex = 3;
|
this.linkLabel1.TabIndex = 3;
|
||||||
|
@ -97,156 +82,52 @@
|
||||||
this.linkLabel1.Text = "https://github.com/gnh1201/welsonjs";
|
this.linkLabel1.Text = "https://github.com/gnh1201/welsonjs";
|
||||||
this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
|
this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
|
||||||
//
|
//
|
||||||
// cbUseSpecificScript
|
// checkBox1
|
||||||
//
|
//
|
||||||
this.cbUseSpecificScript.AutoSize = true;
|
this.checkBox1.AutoSize = true;
|
||||||
this.cbUseSpecificScript.Location = new System.Drawing.Point(26, 281);
|
this.checkBox1.Location = new System.Drawing.Point(26, 263);
|
||||||
this.cbUseSpecificScript.Name = "cbUseSpecificScript";
|
this.checkBox1.Name = "checkBox1";
|
||||||
this.cbUseSpecificScript.Size = new System.Drawing.Size(184, 16);
|
this.checkBox1.Size = new System.Drawing.Size(184, 16);
|
||||||
this.cbUseSpecificScript.TabIndex = 4;
|
this.checkBox1.TabIndex = 4;
|
||||||
this.cbUseSpecificScript.Text = "I want to use specific script ";
|
this.checkBox1.Text = "I want to use specific script ";
|
||||||
this.cbUseSpecificScript.UseVisualStyleBackColor = true;
|
this.checkBox1.UseVisualStyleBackColor = true;
|
||||||
this.cbUseSpecificScript.CheckedChanged += new System.EventHandler(this.cbUseSpecificScript_CheckedChanged);
|
this.checkBox1.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged);
|
||||||
//
|
//
|
||||||
// txtUseSpecificScript
|
// textBox1
|
||||||
//
|
//
|
||||||
this.txtUseSpecificScript.Enabled = false;
|
this.textBox1.Enabled = false;
|
||||||
this.txtUseSpecificScript.Location = new System.Drawing.Point(214, 278);
|
this.textBox1.Location = new System.Drawing.Point(214, 260);
|
||||||
this.txtUseSpecificScript.Name = "txtUseSpecificScript";
|
this.textBox1.Name = "textBox1";
|
||||||
this.txtUseSpecificScript.Size = new System.Drawing.Size(110, 21);
|
this.textBox1.Size = new System.Drawing.Size(110, 21);
|
||||||
this.txtUseSpecificScript.TabIndex = 5;
|
this.textBox1.TabIndex = 5;
|
||||||
//
|
//
|
||||||
// cbInteractiveServiceApp
|
// checkBox2
|
||||||
//
|
//
|
||||||
this.cbInteractiveServiceApp.AutoSize = true;
|
this.checkBox2.AutoSize = true;
|
||||||
this.cbInteractiveServiceApp.Location = new System.Drawing.Point(26, 305);
|
this.checkBox2.Location = new System.Drawing.Point(26, 287);
|
||||||
this.cbInteractiveServiceApp.Name = "cbInteractiveServiceApp";
|
this.checkBox2.Name = "checkBox2";
|
||||||
this.cbInteractiveServiceApp.Size = new System.Drawing.Size(254, 16);
|
this.checkBox2.Size = new System.Drawing.Size(254, 16);
|
||||||
this.cbInteractiveServiceApp.TabIndex = 6;
|
this.checkBox2.TabIndex = 6;
|
||||||
this.cbInteractiveServiceApp.Text = "This is an Interactive Service Application";
|
this.checkBox2.Text = "This is an Interactive Service Application";
|
||||||
this.cbInteractiveServiceApp.UseVisualStyleBackColor = true;
|
this.checkBox2.UseVisualStyleBackColor = true;
|
||||||
//
|
|
||||||
// menuStrip1
|
|
||||||
//
|
|
||||||
this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
|
||||||
this.settingsToolStripMenuItem});
|
|
||||||
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
|
|
||||||
this.menuStrip1.Name = "menuStrip1";
|
|
||||||
this.menuStrip1.Size = new System.Drawing.Size(461, 24);
|
|
||||||
this.menuStrip1.TabIndex = 7;
|
|
||||||
this.menuStrip1.Text = "menuStrip1";
|
|
||||||
//
|
|
||||||
// settingsToolStripMenuItem
|
|
||||||
//
|
|
||||||
this.settingsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
|
||||||
this.userdefinedVariablesToolStripMenuItem,
|
|
||||||
this.instancesToolStripMenuItem,
|
|
||||||
this.runAsAdministratorToolStripMenuItem,
|
|
||||||
this.globalSettingsToolStripMenuItem,
|
|
||||||
this.startCodeEditorToolStripMenuItem,
|
|
||||||
this.openCopilotToolStripMenuItem});
|
|
||||||
this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem";
|
|
||||||
this.settingsToolStripMenuItem.Size = new System.Drawing.Size(62, 20);
|
|
||||||
this.settingsToolStripMenuItem.Text = "Settings";
|
|
||||||
//
|
|
||||||
// userdefinedVariablesToolStripMenuItem
|
|
||||||
//
|
|
||||||
this.userdefinedVariablesToolStripMenuItem.Name = "userdefinedVariablesToolStripMenuItem";
|
|
||||||
this.userdefinedVariablesToolStripMenuItem.Size = new System.Drawing.Size(196, 22);
|
|
||||||
this.userdefinedVariablesToolStripMenuItem.Text = "User-defined variables";
|
|
||||||
this.userdefinedVariablesToolStripMenuItem.Click += new System.EventHandler(this.userdefinedVariablesToolStripMenuItem_Click);
|
|
||||||
//
|
|
||||||
// instancesToolStripMenuItem
|
|
||||||
//
|
|
||||||
this.instancesToolStripMenuItem.Name = "instancesToolStripMenuItem";
|
|
||||||
this.instancesToolStripMenuItem.Size = new System.Drawing.Size(196, 22);
|
|
||||||
this.instancesToolStripMenuItem.Text = "Instances";
|
|
||||||
this.instancesToolStripMenuItem.Click += new System.EventHandler(this.instancesToolStripMenuItem_Click);
|
|
||||||
//
|
|
||||||
// runAsAdministratorToolStripMenuItem
|
|
||||||
//
|
|
||||||
this.runAsAdministratorToolStripMenuItem.Name = "runAsAdministratorToolStripMenuItem";
|
|
||||||
this.runAsAdministratorToolStripMenuItem.Size = new System.Drawing.Size(196, 22);
|
|
||||||
this.runAsAdministratorToolStripMenuItem.Text = "Run as Administrator...";
|
|
||||||
this.runAsAdministratorToolStripMenuItem.Click += new System.EventHandler(this.runAsAdministratorToolStripMenuItem_Click);
|
|
||||||
//
|
|
||||||
// globalSettingsToolStripMenuItem
|
|
||||||
//
|
|
||||||
this.globalSettingsToolStripMenuItem.Name = "globalSettingsToolStripMenuItem";
|
|
||||||
this.globalSettingsToolStripMenuItem.Size = new System.Drawing.Size(196, 22);
|
|
||||||
this.globalSettingsToolStripMenuItem.Text = "Global settings...";
|
|
||||||
this.globalSettingsToolStripMenuItem.Click += new System.EventHandler(this.globalSettingsToolStripMenuItem_Click);
|
|
||||||
//
|
|
||||||
// startCodeEditorToolStripMenuItem
|
|
||||||
//
|
|
||||||
this.startCodeEditorToolStripMenuItem.Name = "startCodeEditorToolStripMenuItem";
|
|
||||||
this.startCodeEditorToolStripMenuItem.Size = new System.Drawing.Size(196, 22);
|
|
||||||
this.startCodeEditorToolStripMenuItem.Text = "Start the code editor...";
|
|
||||||
this.startCodeEditorToolStripMenuItem.Click += new System.EventHandler(this.startCodeEditorToolStripMenuItem_Click);
|
|
||||||
//
|
|
||||||
// openCopilotToolStripMenuItem
|
|
||||||
//
|
|
||||||
this.openCopilotToolStripMenuItem.Name = "openCopilotToolStripMenuItem";
|
|
||||||
this.openCopilotToolStripMenuItem.Size = new System.Drawing.Size(196, 22);
|
|
||||||
this.openCopilotToolStripMenuItem.Text = "Open the Copilot...";
|
|
||||||
this.openCopilotToolStripMenuItem.Click += new System.EventHandler(this.openCopilotToolStripMenuItem_Click);
|
|
||||||
//
|
|
||||||
// notifyIcon1
|
|
||||||
//
|
|
||||||
this.notifyIcon1.ContextMenuStrip = this.contextMenuStrip1;
|
|
||||||
this.notifyIcon1.Icon = global::WelsonJS.Launcher.Properties.Resources.favicon;
|
|
||||||
this.notifyIcon1.Text = "WelsonJS Launcher";
|
|
||||||
//
|
|
||||||
// contextMenuStrip1
|
|
||||||
//
|
|
||||||
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
|
||||||
this.openLauncherToolStripMenuItem,
|
|
||||||
this.openCodeEditorToolStripMenuItem,
|
|
||||||
this.exitToolStripMenuItem});
|
|
||||||
this.contextMenuStrip1.Name = "contextMenuStrip1";
|
|
||||||
this.contextMenuStrip1.Size = new System.Drawing.Size(199, 70);
|
|
||||||
//
|
|
||||||
// openLauncherToolStripMenuItem
|
|
||||||
//
|
|
||||||
this.openLauncherToolStripMenuItem.Name = "openLauncherToolStripMenuItem";
|
|
||||||
this.openLauncherToolStripMenuItem.Size = new System.Drawing.Size(198, 22);
|
|
||||||
this.openLauncherToolStripMenuItem.Text = "Open the launcher...";
|
|
||||||
//
|
|
||||||
// openCodeEditorToolStripMenuItem
|
|
||||||
//
|
|
||||||
this.openCodeEditorToolStripMenuItem.Name = "openCodeEditorToolStripMenuItem";
|
|
||||||
this.openCodeEditorToolStripMenuItem.Size = new System.Drawing.Size(198, 22);
|
|
||||||
this.openCodeEditorToolStripMenuItem.Text = "Open the code editor...";
|
|
||||||
this.openCodeEditorToolStripMenuItem.Click += new System.EventHandler(this.openCodeEditorToolStripMenuItem_Click);
|
|
||||||
//
|
|
||||||
// exitToolStripMenuItem
|
|
||||||
//
|
|
||||||
this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
|
|
||||||
this.exitToolStripMenuItem.Size = new System.Drawing.Size(198, 22);
|
|
||||||
this.exitToolStripMenuItem.Text = "Exit";
|
|
||||||
//
|
//
|
||||||
// MainForm
|
// MainForm
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
|
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.ClientSize = new System.Drawing.Size(461, 382);
|
this.ClientSize = new System.Drawing.Size(461, 362);
|
||||||
this.Controls.Add(this.cbInteractiveServiceApp);
|
this.Controls.Add(this.checkBox2);
|
||||||
this.Controls.Add(this.txtUseSpecificScript);
|
this.Controls.Add(this.textBox1);
|
||||||
this.Controls.Add(this.cbUseSpecificScript);
|
this.Controls.Add(this.checkBox1);
|
||||||
this.Controls.Add(this.linkLabel1);
|
this.Controls.Add(this.linkLabel1);
|
||||||
this.Controls.Add(this.label1);
|
this.Controls.Add(this.label1);
|
||||||
this.Controls.Add(this.btnRunFromExternalLink);
|
this.Controls.Add(this.button2);
|
||||||
this.Controls.Add(this.btnRunFromZipFile);
|
this.Controls.Add(this.button1);
|
||||||
this.Controls.Add(this.menuStrip1);
|
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||||
this.Icon = global::WelsonJS.Launcher.Properties.Resources.favicon;
|
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||||
this.MainMenuStrip = this.menuStrip1;
|
|
||||||
this.MaximizeBox = false;
|
this.MaximizeBox = false;
|
||||||
this.Name = "MainForm";
|
this.Name = "MainForm";
|
||||||
this.Text = "WelsonJS Application Launcher";
|
this.Text = "WelsonJS.Launcher";
|
||||||
this.menuStrip1.ResumeLayout(false);
|
|
||||||
this.menuStrip1.PerformLayout();
|
|
||||||
this.contextMenuStrip1.ResumeLayout(false);
|
|
||||||
this.ResumeLayout(false);
|
this.ResumeLayout(false);
|
||||||
this.PerformLayout();
|
this.PerformLayout();
|
||||||
|
|
||||||
|
@ -254,26 +135,13 @@
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private System.Windows.Forms.Button btnRunFromZipFile;
|
private System.Windows.Forms.Button button1;
|
||||||
private System.Windows.Forms.Button btnRunFromExternalLink;
|
private System.Windows.Forms.Button button2;
|
||||||
private System.Windows.Forms.Label label1;
|
private System.Windows.Forms.Label label1;
|
||||||
private System.Windows.Forms.LinkLabel linkLabel1;
|
private System.Windows.Forms.LinkLabel linkLabel1;
|
||||||
private System.Windows.Forms.CheckBox cbUseSpecificScript;
|
private System.Windows.Forms.CheckBox checkBox1;
|
||||||
private System.Windows.Forms.TextBox txtUseSpecificScript;
|
private System.Windows.Forms.TextBox textBox1;
|
||||||
private System.Windows.Forms.CheckBox cbInteractiveServiceApp;
|
private System.Windows.Forms.CheckBox checkBox2;
|
||||||
private System.Windows.Forms.MenuStrip menuStrip1;
|
|
||||||
private System.Windows.Forms.ToolStripMenuItem settingsToolStripMenuItem;
|
|
||||||
private System.Windows.Forms.ToolStripMenuItem userdefinedVariablesToolStripMenuItem;
|
|
||||||
private System.Windows.Forms.ToolStripMenuItem instancesToolStripMenuItem;
|
|
||||||
private System.Windows.Forms.ToolStripMenuItem runAsAdministratorToolStripMenuItem;
|
|
||||||
private System.Windows.Forms.ToolStripMenuItem globalSettingsToolStripMenuItem;
|
|
||||||
private System.Windows.Forms.ToolStripMenuItem startCodeEditorToolStripMenuItem;
|
|
||||||
private System.Windows.Forms.NotifyIcon notifyIcon1;
|
|
||||||
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
|
|
||||||
private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
|
|
||||||
private System.Windows.Forms.ToolStripMenuItem openCodeEditorToolStripMenuItem;
|
|
||||||
private System.Windows.Forms.ToolStripMenuItem openLauncherToolStripMenuItem;
|
|
||||||
private System.Windows.Forms.ToolStripMenuItem openCopilotToolStripMenuItem;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,116 +1,63 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Security.Principal;
|
using System.IO.Compression;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace WelsonJS.Launcher
|
namespace WelsonJS.Launcher
|
||||||
{
|
{
|
||||||
public partial class MainForm : Form
|
public partial class MainForm : Form
|
||||||
{
|
{
|
||||||
private string workingDirectory;
|
private string workingDirectory;
|
||||||
private string instanceId;
|
private string appName;
|
||||||
private readonly string entryFileName;
|
private readonly string entrypointFileName = "bootstrap.bat";
|
||||||
private string scriptName;
|
private string scriptName;
|
||||||
private readonly ZipExtractor zipExtractor;
|
|
||||||
|
|
||||||
public MainForm()
|
public MainForm()
|
||||||
{
|
{
|
||||||
zipExtractor = new ZipExtractor();
|
|
||||||
|
|
||||||
entryFileName = "bootstrap.bat";
|
|
||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
if (IsInAdministrator())
|
|
||||||
{
|
|
||||||
Text = Text + " (Administrator)";
|
|
||||||
}
|
|
||||||
|
|
||||||
notifyIcon1.DoubleClick += OnShow;
|
|
||||||
openLauncherToolStripMenuItem.Click += OnShow;
|
|
||||||
exitToolStripMenuItem.Click += OnExit;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnFormClosing(FormClosingEventArgs e)
|
|
||||||
{
|
|
||||||
if (e.CloseReason == CloseReason.UserClosing)
|
|
||||||
{
|
|
||||||
e.Cancel = true;
|
|
||||||
this.Hide();
|
|
||||||
this.ShowInTaskbar = false;
|
|
||||||
notifyIcon1.Visible = true;
|
|
||||||
}
|
|
||||||
base.OnFormClosing(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnShow(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
this.Show();
|
|
||||||
this.WindowState = FormWindowState.Normal;
|
|
||||||
this.ShowInTaskbar = true;
|
|
||||||
this.Focus();
|
|
||||||
notifyIcon1.Visible = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnExit(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
notifyIcon1.Visible = false;
|
|
||||||
Application.Exit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnableUI()
|
private void EnableUI()
|
||||||
{
|
{
|
||||||
label1.Text = "Choose the location of WelsonJS application package.";
|
label1.Text = "Choose the location of WelsonJS application package.";
|
||||||
btnRunFromZipFile.Enabled = true;
|
button1.Enabled = true;
|
||||||
btnRunFromExternalLink.Enabled = true;
|
button2.Enabled = true;
|
||||||
cbUseSpecificScript.Enabled = true;
|
checkBox1.Enabled = true;
|
||||||
cbInteractiveServiceApp.Enabled = true;
|
if (checkBox1.Checked)
|
||||||
if (cbUseSpecificScript.Checked)
|
|
||||||
{
|
{
|
||||||
txtUseSpecificScript.Enabled = true;
|
textBox1.Enabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DisableUI()
|
private void DisableUI()
|
||||||
{
|
{
|
||||||
label1.Text = "Please wait...";
|
label1.Text = "Please wait...";
|
||||||
btnRunFromZipFile.Enabled = false;
|
button1.Enabled = false;
|
||||||
btnRunFromExternalLink.Enabled = false;
|
button2.Enabled = false;
|
||||||
cbUseSpecificScript.Enabled = false;
|
checkBox1.Enabled = false;
|
||||||
cbInteractiveServiceApp.Enabled = false;
|
textBox1.Enabled = false;
|
||||||
txtUseSpecificScript.Enabled = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SafeInvoke(Action action)
|
private void button2_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (InvokeRequired)
|
ShowMessageBox("Comming soon...!");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void button1_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Invoke(action);
|
string filePath = OpenFileDialog();
|
||||||
|
if (filePath != null)
|
||||||
|
{
|
||||||
|
string fileExtension = Path.GetExtension(filePath);
|
||||||
|
if (fileExtension != ".zip")
|
||||||
|
{
|
||||||
|
ShowMessageBox("It doesn't seems to a ZIP file.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
action();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void btnRunFromExternalLink_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
MessageBox.Show("Coming soon...!");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void btnRunFromZipFile_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
using (var openFileDialog = new OpenFileDialog())
|
|
||||||
{
|
|
||||||
openFileDialog.Filter = "zip files (*.zip)|*.zip|All files (*.*)|*.*";
|
|
||||||
openFileDialog.FilterIndex = 2;
|
|
||||||
openFileDialog.RestoreDirectory = true;
|
|
||||||
|
|
||||||
if (openFileDialog.ShowDialog() == DialogResult.OK)
|
|
||||||
{
|
|
||||||
string filePath = openFileDialog.FileName;
|
|
||||||
ExtractAndRun(filePath);
|
ExtractAndRun(filePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,9 +65,9 @@ namespace WelsonJS.Launcher
|
||||||
|
|
||||||
private void ExtractAndRun(string filePath)
|
private void ExtractAndRun(string filePath)
|
||||||
{
|
{
|
||||||
instanceId = Guid.NewGuid().ToString();
|
appName = Path.GetFileNameWithoutExtension(filePath);
|
||||||
workingDirectory = Program.GetWorkingDirectory(instanceId);
|
workingDirectory = Path.Combine(Path.GetTempPath(), appName);
|
||||||
scriptName = txtUseSpecificScript.Text;
|
scriptName = textBox1.Text;
|
||||||
|
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
|
@ -132,33 +79,22 @@ namespace WelsonJS.Launcher
|
||||||
Directory.Delete(workingDirectory, true);
|
Directory.Delete(workingDirectory, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to extact ZIP compressed file
|
// try to extact ZIP file
|
||||||
if (zipExtractor.Extract(filePath, workingDirectory))
|
ZipFile.ExtractToDirectory(filePath, workingDirectory);
|
||||||
{
|
|
||||||
// record the first deploy time
|
|
||||||
RecordFirstDeployTime(workingDirectory);
|
|
||||||
|
|
||||||
// follow the sub-directory
|
// If it is created the sub-directory
|
||||||
workingDirectory = Program.GetWorkingDirectory(instanceId, true);
|
workingDirectory = GetFinalDirectory(workingDirectory);
|
||||||
|
|
||||||
// Run the application
|
// Run the appliction
|
||||||
Program.RunCommandPrompt(workingDirectory, entryFileName, scriptName, cbUseSpecificScript.Checked, cbInteractiveServiceApp.Checked);
|
RunCommandPrompt();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MessageBox.Show("Failed to extract the ZIP file.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
SafeInvoke(() =>
|
ShowMessageBox(ex.Message);
|
||||||
{
|
|
||||||
MessageBox.Show("Error: " + ex.Message);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable UI
|
// Enable UI
|
||||||
SafeInvoke(() => {
|
label1.Invoke((MethodInvoker)delegate {
|
||||||
EnableUI();
|
EnableUI();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -166,117 +102,111 @@ namespace WelsonJS.Launcher
|
||||||
DisableUI();
|
DisableUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RecordFirstDeployTime(string directory)
|
private void RunCommandPrompt()
|
||||||
{
|
{
|
||||||
try
|
bool isConsoleApplication = checkBox1.Checked;
|
||||||
{
|
bool isInteractiveServiceAapplication = checkBox2.Checked;
|
||||||
string filePath = Path.Combine(directory, ".welsonjs_first_deploy_time");
|
|
||||||
string text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
|
||||||
|
|
||||||
File.WriteAllText(filePath, text);
|
if (!isConsoleApplication)
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
{
|
||||||
throw new Exception($"Failed to record first deploy time: {ex.Message}");
|
if (!File.Exists(Path.Combine(workingDirectory, entrypointFileName)))
|
||||||
|
{
|
||||||
|
throw new Exception("Not Found: " + entrypointFileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!Directory.EnumerateFiles(workingDirectory, scriptName + ".*").Any())
|
||||||
|
{
|
||||||
|
throw new Exception("Not found matches file: " + scriptName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsInAdministrator()
|
Process process = new Process
|
||||||
{
|
{
|
||||||
try
|
StartInfo = new ProcessStartInfo("cmd")
|
||||||
{
|
{
|
||||||
WindowsPrincipal wp = new WindowsPrincipal(WindowsIdentity.GetCurrent());
|
UseShellExecute = false,
|
||||||
return wp.IsInRole(WindowsBuiltInRole.Administrator);
|
RedirectStandardInput = true,
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
CreateNoWindow = true,
|
||||||
|
Arguments = "/k",
|
||||||
}
|
}
|
||||||
catch
|
};
|
||||||
|
process.Start();
|
||||||
|
|
||||||
|
process.StandardInput.WriteLine("pushd " + workingDirectory);
|
||||||
|
process.StandardInput.WriteLine();
|
||||||
|
process.StandardInput.Flush();
|
||||||
|
process.StandardOutput.ReadLine();
|
||||||
|
|
||||||
|
if (isInteractiveServiceAapplication)
|
||||||
{
|
{
|
||||||
return false;
|
process.StandardInput.WriteLine($"start cmd /c startInteractiveService.bat");
|
||||||
|
process.StandardInput.WriteLine();
|
||||||
|
process.StandardInput.Flush();
|
||||||
|
process.StandardOutput.ReadLine();
|
||||||
|
}
|
||||||
|
else if (!isConsoleApplication)
|
||||||
|
{
|
||||||
|
process.StandardInput.WriteLine(entrypointFileName);
|
||||||
|
process.StandardInput.WriteLine();
|
||||||
|
process.StandardInput.Flush();
|
||||||
|
process.StandardOutput.ReadLine();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
process.StandardInput.WriteLine($"start cmd /c cscript app.js {scriptName}");
|
||||||
|
process.StandardInput.WriteLine();
|
||||||
|
process.StandardInput.Flush();
|
||||||
|
process.StandardOutput.ReadLine();
|
||||||
|
}
|
||||||
|
process.StandardInput.Close();
|
||||||
|
process.WaitForExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
private string OpenFileDialog()
|
||||||
|
{
|
||||||
|
string filePath = null;
|
||||||
|
|
||||||
|
using (OpenFileDialog openFileDialog = new OpenFileDialog())
|
||||||
|
{
|
||||||
|
if (openFileDialog.ShowDialog() == DialogResult.OK)
|
||||||
|
{
|
||||||
|
//Get the path of specified file
|
||||||
|
filePath = openFileDialog.FileName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cbUseSpecificScript_CheckedChanged(object sender, EventArgs e)
|
return filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowMessageBox(string message)
|
||||||
{
|
{
|
||||||
txtUseSpecificScript.Enabled = cbUseSpecificScript.Checked;
|
MessageBox.Show(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetFinalDirectory(string path)
|
||||||
|
{
|
||||||
|
string[] directories = Directory.GetDirectories(path);
|
||||||
|
|
||||||
|
while (directories.Length == 1)
|
||||||
|
{
|
||||||
|
path = directories[0];
|
||||||
|
directories = Directory.GetDirectories(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkBox1_CheckedChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
textBox1.Enabled = checkBox1.Checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||||
{
|
{
|
||||||
Program.OpenWebBrowser(Program.GetAppConfig("RepositoryUrl"));
|
System.Diagnostics.Process.Start("https://github.com/gnh1201/welsonjs");
|
||||||
}
|
|
||||||
|
|
||||||
private void userdefinedVariablesToolStripMenuItem_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
(new EnvForm()).Show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void instancesToolStripMenuItem_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
(new InstancesForm()).Show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void runAsAdministratorToolStripMenuItem_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (!IsInAdministrator())
|
|
||||||
{
|
|
||||||
ProcessStartInfo procInfo = new ProcessStartInfo
|
|
||||||
{
|
|
||||||
UseShellExecute = true,
|
|
||||||
FileName = Application.ExecutablePath,
|
|
||||||
WorkingDirectory = Environment.CurrentDirectory,
|
|
||||||
Verb = "runas"
|
|
||||||
};
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Process.Start(procInfo);
|
|
||||||
Application.Exit();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
MessageBox.Show("Failed to run as administrator: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MessageBox.Show("Already running as Administrator.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void globalSettingsToolStripMenuItem_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
(new GlobalSettingsForm()).Show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startCodeEditorToolStripMenuItem_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
Program.StartResourceServer();
|
|
||||||
|
|
||||||
if (!Program.resourceServer.IsRunning())
|
|
||||||
{
|
|
||||||
Program.resourceServer.Start();
|
|
||||||
((ToolStripMenuItem)sender).Text = "Open the code editor...";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Program.OpenWebBrowser(Program.resourceServer.GetPrefix());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void openCodeEditorToolStripMenuItem_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
if (Program.resourceServer == null)
|
|
||||||
{
|
|
||||||
MessageBox.Show("A resource server is not running.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Program.OpenWebBrowser(Program.resourceServer.GetPrefix());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void openCopilotToolStripMenuItem_Click(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
Program.OpenWebBrowser(Program.GetAppConfig("CopilotUrl"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,13 +117,968 @@
|
||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||||
<value>17, 17</value>
|
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
</metadata>
|
<value>
|
||||||
<metadata name="notifyIcon1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
AAABAA0AICAQAAEABADoAgAA1gAAABAQEAABAAQAKAEAAL4DAAAwMAAAAQAIAKgOAADmBAAAICAAAAEA
|
||||||
<value>134, 17</value>
|
CACoCAAAjhMAABAQAAABAAgAaAUAADYcAAAAAAAAAQAgAIEXAACeIQAAQEAAAAEAIAAoQgAAHzkAADAw
|
||||||
</metadata>
|
AAABACAAqCUAAEd7AAAoKAAAAQAgAGgaAADvoAAAICAAAAEAIACoEAAAV7sAABgYAAABACAAiAkAAP/L
|
||||||
<metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
AAAUFAAAAQAgALgGAACH1QAAEBAAAAEAIABoBAAAP9wAACgAAAAgAAAAQAAAAAEABAAAAAAAgAIAAAAA
|
||||||
<value>249, 17</value>
|
AAAAAAAAEAAAAAAAAAAAAAAAAACAAACAAAAAgIAAgAAAAIAAgACAgAAAgICAAMDAwAAAAP8AAP8AAAD/
|
||||||
</metadata>
|
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
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAD///////8AAP///////wAA////////AAD///////8AAP///////wAA////////AAD//wA/4AMAAP//
|
||||||
|
AD/gAwAA//wAB+ADAAAAQAABg+AAAIBgAAGD4AAAgCAAAP/gAADAMBAA/+AAAMAwEAB/4AAA4BAYAH8D
|
||||||
|
AADgGAgAPwMAAPAIDAA8HwAA8AwEBBwfAAD4BAYEHB8AAPgGAgYA/wAA+AICAgD/AAD8AwECA/8AAPwB
|
||||||
|
AQMD/wAA/gGAAQP/AAD+AIABg+AAAP8AwACD4AAA/wBAAIADAAD/gGAAQAMAAP+AIABgAwAA/8AgMCD/
|
||||||
|
AAD/wDAQMH8AAP/gEBgQfwAA/+AYCBg/AAD/8AgMCD8AAP/wDAQMPwAA//AEBgQfAAD/+AYCBB8AAP/4
|
||||||
|
AgMGDwAA//wDAQIPAAD//AEBgwcAAP/+AYGBBwAA//4BgIGDAAD///////8AAP///////wAA////////
|
||||||
|
AAD///////8AAP///////wAA////////AAAoAAAAIAAAAEAAAAABAAgAAAAAAIAEAAAAAAAAAAAAAAAB
|
||||||
|
AAAAAAAAAAAAAAAMEAAQEBAAHx0cAAAjMAAgICAAMDAwAD87NAAAL0AAMFJfACNbbwBAQEAAVFxgAGBg
|
||||||
|
YABoeW0Af39/AM96AADOfw0Aj3BHAACCMAAAmjkAAKU9AA2dQwAAvUYAV5huAGuFdAAQwVEAIMVdADDK
|
||||||
|
aABAznMAS8V4AO+NAAD/lgAA/5wQAM+ONAD/oyAA/6kwAK+LVwCOiH0A/7BAAP+2UADOo2cA3rFvAP++
|
||||||
|
YAD/xHAA/8l/AAltjwAkc48AADH/ABA9/wAgSv8AMFf/AEBk/wBQcv8AYH//AACCrwBns4MAQpKuAFDR
|
||||||
|
gABg1YwAf9yiAACazwA0ps8AKrHfAAC9/wBns84AcIz/AH+X/wAQwf8AIMX/AEDO/wBQ0f8AcNn/AH/c
|
||||||
|
/wBR/4cAcf+dAJH/sgCx/8kA0f/fAP///wAAAAAAAi8AAARQAAAGcAAACJAAAAqwAAALzwAADvAAACD/
|
||||||
|
EgA9/zEAW/9RAHn/cQCY/5EAtf+xANT/0QD///8AAAAAABQvAAAiUAAAMHAAAD2QAABMsAAAWc8AAGfw
|
||||||
|
AAB4/xEAiv8xAJz/UQCu/3EAwP+RANL/sQDk/9EA////AAAAAAAmLwAAQFAAAFpwAAB0kAAAjrAAAKnP
|
||||||
|
AADC8AAA0f8RANj/MQDe/1EA4/9xAOn/kQDv/7EA9v/RAP///wAAAAAALyYAAFBBAABwWwAAkHQAALCO
|
||||||
|
AADPqQAA8MMAAP/SEQD/2DEA/91RAP/kcQD/6pEA//CxAP/20QD///8AAAAAAC8UAABQIgAAcDAAAJA+
|
||||||
|
AACwTQAAz1sAAPBpAAD/eREA/4oxAP+dUQD/r3EA/8GRAP/SsQD/5dEA////AAAAAAAvAwAAUAQAAHAG
|
||||||
|
AACQCQAAsAoAAM8MAADwDgAA/yASAP8+MQD/XFEA/3pxAP+XkQD/trEA/9TRAP///wAAAAAALwAOAFAA
|
||||||
|
FwBwACEAkAArALAANgDPAEAA8ABJAP8RWgD/MXAA/1GGAP9xnAD/kbIA/7HIAP/R3wD///8AAAAAAC8A
|
||||||
|
IABQADYAcABMAJAAYgCwAHgAzwCOAPAApAD/EbMA/zG+AP9RxwD/cdEA/5HcAP+x5QD/0fAA////AAAA
|
||||||
|
AAAsAC8ASwBQAGkAcACHAJAApQCwAMQAzwDhAPAA8BH/APIx/wD0Uf8A9nH/APeR/wD5sf8A+9H/AP//
|
||||||
|
/wAAAAAAGwAvAC0AUAA/AHAAUgCQAGMAsAB2AM8AiADwAJkR/wCmMf8AtFH/AMJx/wDPkf8A3LH/AOvR
|
||||||
|
/wD///8AAAAAAAgALwAOAFAAFQBwABsAkAAhALAAJgDPACwA8AA+Ef8AWDH/AHFR/wCMcf8AppH/AL+x
|
||||||
|
/wDa0f8A////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
DgADBwcHAAwAAAAAAA0ABgsLBgAAADYwMDAwNAAaFwAAABIgIBAAAAA9SQAAAAAAAAAAAAAAADAwMDAw
|
||||||
|
ADsXAAAAJiEgEAAAAD1EAAAAAAAAAAAAAAAANTAwMDA1ABcAAAAZLCAQAAAAPUBJAAAAAAAAAAAAAAAA
|
||||||
|
MDAwMDAAOhUVFR4AIRAAAAA9QEUAAAAAAAUCAAAAAAA0MDAwMDUAFxcXFwArEAAAAD5AQAAAAAAAAAAG
|
||||||
|
AAAAAAAwMDAwMQAdFxcXOgAQAAAAAEBARQAACwAADQAAAAAAADMwMDAwQgAXFxcXACIAAAAARkBAAA8F
|
||||||
|
Ag8AAAAAAAAAADAwMDAxABwXFxc7AAAAACkAQEAvAAACAAAAAAAAAAAAMjAwMDBDABcXFxoAAAAAEQA/
|
||||||
|
BAEAAAAAAAAAAAAAAABDMDAwMDEAGxcXFzgAAAAQLQAAAAAAAAAAAAAAAAAAAAAyMDAwMEM8FxcXFgAA
|
||||||
|
ABAhAAAAAAAAAAAAAAAAAAAAAEMwMDAwMgAaFxcUAAAAECAqCQgACgAADQALDQAAAAAAADEwMDAwADwX
|
||||||
|
FxQAAAAQICMALgAAAAAAAAAAAAAAAAAAQzAwMDAzABoXFRMYJR8gIABBNzc5AAAAAAAAAAAAAAAAMTAw
|
||||||
|
MDAAPBcXFxsAISAgJABEQEQAAAAAAAAAAAAAAAA2MDAwMDQAGhcXFwAtICAgAEhAQEkAAAAAAAAAAAAA
|
||||||
|
AAAwMDAwMAA7FxcXHAAhICAoAEBARAAAAAAAAAAAAAAAADUwMDAwNQAXFxcXAC0gICAAR0BASQAAAAAA
|
||||||
|
AAAAAAAAADAwMDAwADoXFxcdACEgICgAQEBEAAAAAAAAAAAAAAAANDAwMDA1ABcXFxcAKyAgIABGQEBJ
|
||||||
|
AAAAAAAAAAAAAAAAMDAwMDAAHRcXFzoAICAgKwBAQEUAAAAAAAAAAAAAAAA0MTExMUIAGhoaGgAnISEj
|
||||||
|
AEZERAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAD//////////////////////+A/A//APgMCAAR4ggAH+IEAA/jBBAPjwIQD4+CC
|
||||||
|
EYfgQhEP8EEIH/AhCH/wIAR/+AAEePgQADD8EAID/AgCH/4IIR/+BCEP/wQQj/8CEIf/gghH/4EIQ//B
|
||||||
|
BCP/wIQj/////////////////////ygAAAAQAAAAIAAAAAEACAAAAAAAQAEAAAAAAAAAAAAAAAEAAAAA
|
||||||
|
AAAAAAAADw8PAAAMEAAQEBAAHx0cAAwmMAAgICAAMDAwAGA4AAAAUx8AAF8jACRPNQBgRB4APEtPAABH
|
||||||
|
YAAeT2AAQEBAAEZNSABIUk0ASFlfAFBQUABgYGAAnm0oABaHQAAAsUIAAL1GABDBUQBAznMAS8V4AO+N
|
||||||
|
AAD/lgAA/5wQAP+jIAD/qTAAv45IAO6rSwDusloAADH/ABA9/wAgSv8AMFf/AEBk/wBQcv8AYH//AFDR
|
||||||
|
gABg1YwAcNmXAHjXogAnpM4AAL3/AHeZ8gB/l/8AIMX/AEDO/wBQ0f8AYNX/AH/b+AB/3P8Apr6LAI23
|
||||||
|
vQCH2JgA78mHANH/8AD///8AAAAAAAAvDgAAUBgAAHAiAACQLAAAsDYAAM9AAADwSgAR/1sAMf9xAFH/
|
||||||
|
hwBx/50Akf+yALH/yQDR/98A////AAAAAAACLwAABFAAAAZwAAAIkAAACrAAAAvPAAAO8AAAIP8SAD3/
|
||||||
|
MQBb/1EAef9xAJj/kQC1/7EA1P/RAP///wAAAAAAFC8AACJQAAAwcAAAPZAAAEywAABZzwAAZ/AAAHj/
|
||||||
|
EQCK/zEAnP9RAK7/cQDA/5EA0v+xAOT/0QD///8AAAAAACYvAABAUAAAWnAAAHSQAACOsAAAqc8AAMLw
|
||||||
|
AADR/xEA2P8xAN7/UQDj/3EA6f+RAO//sQD2/9EA////AAAAAAAvJgAAUEEAAHBbAACQdAAAsI4AAM+p
|
||||||
|
AADwwwAA/9IRAP/YMQD/3VEA/+RxAP/qkQD/8LEA//bRAP///wAAAAAALxQAAFAiAABwMAAAkD4AALBN
|
||||||
|
AADPWwAA8GkAAP95EQD/ijEA/51RAP+vcQD/wZEA/9KxAP/l0QD///8AAAAAAC8DAABQBAAAcAYAAJAJ
|
||||||
|
AACwCgAAzwwAAPAOAAD/IBIA/z4xAP9cUQD/enEA/5eRAP+2sQD/1NEA////AAAAAAAvAA4AUAAXAHAA
|
||||||
|
IQCQACsAsAA2AM8AQADwAEkA/xFaAP8xcAD/UYYA/3GcAP+RsgD/scgA/9HfAP///wAAAAAALwAgAFAA
|
||||||
|
NgBwAEwAkABiALAAeADPAI4A8ACkAP8RswD/Mb4A/1HHAP9x0QD/kdwA/7HlAP/R8AD///8AAAAAACwA
|
||||||
|
LwBLAFAAaQBwAIcAkAClALAAxADPAOEA8ADwEf8A8jH/APRR/wD2cf8A95H/APmx/wD70f8A////AAAA
|
||||||
|
AAAbAC8ALQBQAD8AcABSAJAAYwCwAHYAzwCIAPAAmRH/AKYx/wC0Uf8AwnH/AM+R/wDcsf8A69H/AP//
|
||||||
|
/wAAAAAACAAvAA4AUAAVAHAAGwCQACEAsAAmAM8ALADwAD4R/wBYMf8AcVH/AIxx/wCmkf8Av7H/ANrR
|
||||||
|
/wD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEBBBAAAAAABgMAKiUmAAoA
|
||||||
|
Ih0ADjkUAAAUAAAlJTIXCTodAA80AAAABhUAKSUmLxksIwASMQAABxUAAAAlJTIaGQAADDUwBhUAAAAA
|
||||||
|
KSUnLxkcAAgAAg0AAAAAAAAlJQAaGAAIJAUPAAcGAAAAKCUoLhkLFh87DhMVAAAAAAAlJQAZGgAePTQ2
|
||||||
|
AAAAAAAAJyUpLRk8IR84MQAAAAAAADMlJQAZGgAePTQ3AAAAAAAAJiYrGxoAICA5NAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AAD//wAA+HEAABAMAACAHAAAgBkAAMEDAADAJwAA5AQAAOAB
|
||||||
|
AADyQwAA8AMAAPEhAAD4IQAA//8AAP//AACJUE5HDQoaCgAAAA1JSERSAAABAAAAAQAIBgAAAFxyqGYA
|
||||||
|
ABdISURBVHja7Z1faFxXfsd/V4HNFkLXbbclpNCMoSw0sMTy0rJLCSv/kRxKiW3Sl1DaHT1t47Ss9VhK
|
||||||
|
N852KaUUJAiWH63dlj4ljfNQGktRrHR3IfTBlumfpe2DRQhp2P5Bad0uNrFuzxlJ0Yw1c865954/v985
|
||||||
|
3w9oWeKR5szMvZ/vzJn7PaciAECxVKkHAABIBwQAQMFAAAAUDAQAQMFAAAAUDAQAQMFAAAAUDAQAQMFA
|
||||||
|
AAAUDAQAQMFAAAAUDAQAQMFAAAAUDAQAQMFAAAAUDAQAQMFAAAAUDAQAQMFAAAAUDAQAQMFAAAAUDAQA
|
||||||
|
QMFAAAAUDAQAQMFAAAAUDAQAQMFAAAAUDAQAQMFAAAAUDAQAQMFAAAAUDATgifoY9WiKvpF6HM7s0CvV
|
||||||
|
Jm2bbjK3RpfUY/pc6qEOqOnd1dN0zXibV+sZeoTOJhjbx3Sflmihmvh81jfoiHrOXw4+lin1up4wv67D
|
||||||
|
QACeqI/TVXUg9FOPw4mKrlU36bzpJnNv0zl1uzdSD3WfnR068fYsbRhvtKxOM6KZ6IOraIVerOZNN6l3
|
||||||
|
ZRpWABVtVCfpRLNfAZ0ZpH9Ft9T/PZJ6LG4DphMq/TdMN5l9h25UdYKTadxw1YG9Zjuwl+tz6n/TCKum
|
||||||
|
aXpJPaOT/nk3/fXx0Qs8jvOV7V3SQ0AAHlACuKSeyfBv7/ywUd0yn0zc0l8f2Na3/6nSn9S4LlTGd1N1
|
||||||
|
jOezok2V/tPNfw10Qp38R9SzeIfkpP95lVXGk4lT+usDe9V2YO9+9r+RZHwPlEx/r9ow3aR+R6V/TccC
|
||||||
|
j2S+OqU+ijQEAuiIsPTfVOlvPJlOr9HM1FSik2kMtTqw12wH9pU61fwLj/Qn2qIpmm4y+bcPBNABgek/
|
||||||
|
r9J/xXSTM+t0VZ10/dRD3WPrvjqwN0wH9pW6px5XmvkXt/S/QaHfTelvdGZVELUAAuiAsPTf0pNVpq/+
|
||||||
|
nr1BvZ0dRpOZ6sBetR3Yy/Wi+t+LCUa3odLfOJdSq3dTFP7d1La6j6Nt0l8DAbRkL/3Dz+x6G/Dge/9L
|
||||||
|
ppvMrVOqk2kc2yr9j7JNf/Vuil6qVow3WR+89T8XdBwd0l8DAbRECaCvnr2rqcfhyLY6YI9ml/6X61Tv
|
||||||
|
wLboHk0bL/xZpWP0yOD5DMn23mf/rbZ/AAJoST09eHFDz+x6GqxD+se4UMWd7Sl1YL9lOrAX6yP0aLL5
|
||||||
|
lwX19n/JdAOV/joc+kFH0TH9NRBAC1T68/qe3Mz23mf/rUk3mLlBRz6zw2gyU3r6q3dTFP7dVOf010AA
|
||||||
|
LVDpn+qikxaDzTb908y/qOdTffa/ZLxJnOfzWnXKfDm3CxBAQzJNf06TmddWbQf25TrV/Mu2Sv+jDqWf
|
||||||
|
8O+mduhEZetGOAABNKQ+rk7+OvDMri8cSj+z69RXBwGbyUzH0k+a+ZfM0l8DATRApf+xva/+ZOBQ+pmL
|
||||||
|
c5mqK/b0T1f62Vav/TS9WG1NuoG09NdAAA1A5TcsqPw6jaNx5df854ATqPwGHi4qv67jaFz5NQEBOCLs
|
||||||
|
sl9Ufv1iL/2sD94Zhp1LaVn5Nf9JYEVg6QeVX58Ir/yagAAcEJb+eVZ+l+vw19WPR3zl1wQEYEFg+lsr
|
||||||
|
v3MxSiru2Cu/l+t0375kUPk1AQFYEJb+1srv7Codq8KXVNxxuew33YIf9spvnPTvVPk1AQEYyLHyy2zB
|
||||||
|
D96VX6LzSgDGuRTJ6a+BAAyg8hsY3qWfTXXyG+dSIlZ+g6S/BgIwgMpvUOzpn7Ly67bgh4jKrwkIYAIC
|
||||||
|
Sz/G9EfltxFZVX5NQAATQOU3KPIrv3GWT1upTtF89z8zGQhgDALTX1TlVx10K9dtB/ZyrU+uxQTD41P5
|
||||||
|
faBe1zna7P6HJgMBjEFU+lcqJW6aT6Yz63SxTnMyjaVWB/aa6cDmnv7CKr8mIICHUOk/o54VNlfJ2Qc8
|
||||||
|
SP+JJ9Mg/evBV1VcJjNR+XXBY+XXBATwELkt+MGt9MO68ku0RBeqBdMNckp/DQQwxF7l907qcbgPWFbl
|
||||||
|
l7inv3o+c6z8moAAhlDpv6iefC4bY5gRmP6o/DoQoPJrvjswQOCCH6j8+iTjyq8JCGAPYaUfVH79knXl
|
||||||
|
1wQEQKj8RgCVXxcCX/Y7DgiAxKU/Kr9+yb7ya6J4AaDyGxxUfl1IkP4aCACV37DwLv3YK79r6sQPP5eS
|
||||||
|
JP01EAAqvyHJofIbfi4lUfprihaAwNIPKr/+cK38hr4wLHjl10TZApBU+hGY/o6V31TpX0zl10SxAhCY
|
||||||
|
/i6VXzbp71T5TZf+LpXfGAt+RKn8mihXAJLS36Hyyyz9Ufl1I1rpZxJFCiDLyi+jBT+Ie+mHy4IfkSq/
|
||||||
|
JsoUACq/QXGs/Kb59gXpP0JxAlDpn+6S01YDtld+5+KUVFzhnf5uC36EfzfFIP015QngOKW65LQ5+aZ/
|
||||||
|
mvmXilbUyW+cS6nXKfxahBVtVLat0KM9JQUhsPIrasGPWh3Ya7YDO2Xlt1bpb1jwY3CTDCu/JkoTgKTS
|
||||||
|
z0Z1y3wyofLbiGIrvyaKEQAqv8FB5deNBZX+S0megzGUJABJ6S+u8qsOpIXrtgM7XeUX6T+BIgQgsPK7
|
||||||
|
oE5+48nErPJrT39UfpOWfiZRigCySn9UfhtRfOXXRPYCEJj+4ko/qPw6wDD9NSUIgNX35BZQ+fWLvfK7
|
||||||
|
Ssco/FxK0sqvifwFIKn0IzD9M6j86tWg+oFHkrTyayJrAQhMf1R+/YHKrwN5C0BS+qPy63lwKP24kK0A
|
||||||
|
UPkNjr30c7lOteAqKr+O5CuAzCq/s+vUr0LvS9cAVH6dYJ3+miwFgMpvcFD5dYF5+mvyFAAqv0ERX/mN
|
||||||
|
kf6MKr/mYWYGKr+Bh+tS+U2X/tbKb7T017s327ZCZ0COApB02a+18sst/fWBvWo7sFOlP5fST0WblW0r
|
||||||
|
dCZkJQCBld/zKquMJxOn9NcH9qrtwEblV8Oq8msiNwFISv9Nlf7GkwmV30bwSH+GlV8T2QhAYPpbF/xA
|
||||||
|
5bcBXNKfaelnEjkJQFL6J6/8fnid6L9uu9/+/z6gze1/tFzO+oUTv0I//eRTh/7702fVT9BLMjZU+hvn
|
||||||
|
UvYrvwvLRNt3wwzikwd0//W/pdd+fJ/uh3ywE3iTqPmkYxYCyLLyG3hfun/4010JROGkehi/EXCh3QaV
|
||||||
|
36O/qez7UaTHHZcF9dN43iEXAaS65LQNLCq/GQmgUeUXAhglDwFMU5pLTlsNlkflNyMBLKi3/8YDf7jy
|
||||||
|
CwGMIl4AqPy2IxMB2NP/ocovBDCKfAFIqvwySX9NFgJoUfqBAEYRLYBM0z/KZGYGAmhV+YUARpEtAFR+
|
||||||
|
WyNeAC0rvxDAKGIFgMpvN4QLwLXye2guBQIYRa4AUPnthGgBdKj8QgCjiBQAKr/dES2ADpVfCGAUqQKQ
|
||||||
|
dNkvy8qvYAHYSz/rg3eGY+dSIIBRxAlAYOmHZeVXrADcSj8T51IggFEkCkBS+lsrv6fXaGYq/L50hxAq
|
||||||
|
gM6VXwhgFFECEJj+1srvXIx96cYgUgCj6a+LUgEbRgec+1WiN7419B/CVn576udOjMelkSYASenvWvmN
|
||||||
|
9mIPI1AAD1d+Uwkg9C6/PYIADoPKr18ECuC8EsDwXEoaAYRf8KNHEMBhcqv8hl7ww4YwAWyqk//huZQU
|
||||||
|
Agid/poeQQCHQeXXL8IEMK7yG18AcZb76hEEMIrA0k/yBT9sCBLApMpvbAFs7y32uRX47noEAYyCyq9/
|
||||||
|
xAhgcukntgBi7fPXIwjgAIHpz6bya0KIAEyV37gCeFm9rnOWRVH90CMI4ABR6V/RSnWTjCWVM+t0sY50
|
||||||
|
4JoQIQBz5TeaAJ75Iv3b9/6enohxXwQBHKDSf0aNMPpVcu0HPEh/Y0pw2eVXgABsld9oAnji8/T9D/+D
|
||||||
|
nolxXwQBHIDKbzgECGCJLlQLhn+PJgDaXW8/xud/TY8gAFR+Q7P5TfroRz+gx6PcWXMB6LmUE6bK7898
|
||||||
|
jn7/Pz+mP44yfgggPir9F9VBkOQqucYIS3/ND+bpnf99n05GubPmArCWfp5/hv7y9e/RC1HGDwHERWD6
|
||||||
|
s6z8TmR3l1+drv0o99dUAA6V32/N0wffvEo/H2X8cQWgj/loXxFzFYCk0g/byu8kaqL5tVP0VeIpAKfK
|
||||||
|
79Jf0Rt6n79IxBRAVNgJAJXf4Ozv8qvPyH6Ue2wiAMddfpdeoxkIoDscBSAp/a2V39lVOlY9wmj14h16
|
||||||
|
ZXX3evZPt8sKjrsA7Lv87s2lLL1OBAF0h5UAcqz8nlmnq3WsE83Otkr/oxu7bTaOAni48nsInf7qeZ+B
|
||||||
|
APzATQCo/IbkIP013AQwrvI7Qr1GM7Q3lwIB+IGXAFD5Dclw+mt4CaCmeXqpWjHeZGiXXwjAD2wEILD0
|
||||||
|
w77yO8Jo+ms4CaDxLr8QgB/4CEBS6Udg+k9N0fRbo112PgJw2efvoeXTIAA/sBCAwPQXUfndR73IK9dP
|
||||||
|
HWopchGAyy6/I+mvgQD8wEMAktLfofLLLP2pfkDTa4e77DwE0HKXXwjAD8kFkFvll1v6K66tjl/JhoMA
|
||||||
|
XNJ/7C6/EIAf0gvguHrrX7O5Ss6MwNLPzg6deHt2bEsxvQBapr8GAvBDUgGo9D+2d+GPDIRVfmly+mtS
|
||||||
|
C8C24Idxl18IwA9pBYDKb1hqOr96emJLMbUAOu3yq2mzx9/015V57rZ6FFstfkfPFW20urdIJBOAwMqv
|
||||||
|
rPTfrfyarqxLK4Bajc2w4MfgJgGWT4u8OagW3LXOfyUgKQUgqfSzUd0iY0mFaeV3xXCTlALovMtvWyCA
|
||||||
|
UZIIAJXf4OxXfidvYXXkiTdp+8PnoozmYQE4Vn4pwLspCGCUVAKQlP6SK7+T+aW5f6Ufrv5ilPGMCsC5
|
||||||
|
8htiKBDAKNEFILDyu6BO/iXTTRhXfsdzpe7R1d/6Z/q7v/hMlBGNCsC58htiKBDAKCkEcFHda/KNMRyx
|
||||||
|
pj/zyu94LteX6M/nX6b3VuKM6UAAjSq/IYAARokqgL301y8uKr9hsKf/Yn2EHqU79N35I9EF4Fb5DTqX
|
||||||
|
AgGMElsAvL4nN5ND5fcwOv31/Mt35ymyAOyV31UVDIHnUp58gXbe/5FSdhwggGFElX4Epv+Yyu8o++mv
|
||||||
|
hRVbAM8vulR+g381+XPP091/36bH4jxwCOBTBKa/S+WXTfpPqPyOsp/+mpgCmPnde3T21cebVn5D8Nkz
|
||||||
|
9OG9T6Jt9AkB7CMq/fOp/B6wm/4H377EFMBTz75H//TWV4zjj/N8XqtODeafenEeOAQwAJXf4JhKP7tc
|
||||||
|
rkcXXI0pgEcfu0L37l6Y9M+TKr/e2aET1ezgOejFeeAQwIDcKr+z69SviM/qxYbK7wHL9eiCqzEFQIPr
|
||||||
|
KCbu9Bsx/fXrqr+P7DX8XX37Nt9c6cf9bsPf0R+TNgI/F58SXAA5Vn7nApRUOmBP/+Vay3d0/oWJAEyV
|
||||||
|
X6/spv9Gy98+/PyFY0v9HI10XxEEcFwlZc3mKjkzAiu/jul/eP6FiwDWB3XwsBeGVbRRnTSXuSxAAG1A
|
||||||
|
5TfwcNWBvWY7sMelv4aBAKKlv969+XSnz+IQQBuElX6slV9u6W9Z8GOX5Xr8lXUcBBDn+dxSn/27nlAQ
|
||||||
|
QFMEVn7Pq/Q3nkzcKr+rtgP7cj15/oWDAAKWfoZYUAJY6vg3IICmCEv/TZX+xpIKt8qveuEWrtsO7Cv1
|
||||||
|
5PmXxAKIlf40RdOVqRvhBgTQBIGVX+uCH8wqv/YFP3TltzbMv6QWQIz036FXKls3wg0IoAnC0j/fyq/p
|
||||||
|
NUgogNCV3z221X0c9ZD+GgjAFYHpL67041z5NQkrpQBizKX4S38iCMAdgaWffCu/JhIJIEbll3bTX3/2
|
||||||
|
3/L09yAAV0SVfgSmf6PKr4lUAohQ+VWsVLZmZDMgABcEpn/elV8TCQQQq/JLD9TrampGNgcCcEFU+le0
|
||||||
|
VN2cXFDRMEv/5pVfEykEELf04xMIwIawyq9r+nOazGxe+TURWQAq/V+JWPnd8PxXe9SuDfhyi99r2wb8
|
||||||
|
DrWoHvsTACq/QWlV+TURWwBr9LHQ9O9CzCtH9bvZxlc8ehEAKr/BaVf5NRFRAI99lq78z1/TCyQz/btQ
|
||||||
|
iABQ+Q1K68qviYgCePaX6b2/+RP6ctA76V75DUH+AkDlN/Bwu1R+TUQUwO/8Ov33lQX6yaB30r3yG4Ii
|
||||||
|
BCDpst9cK7/Nv32JKICLzxMtXuj+dyZS0WZl3go9FXkLIMfKL6f01wf2qu3AfrWeoUdafPuSkwCI5ivz
|
||||||
|
VuipyF4AktLfWvk9vUYzU+FLKs7U6sBesx3YpsqviXwE4KvyG4J8BSAw/cur/JrIRQB+Sz++yVoAktI/
|
||||||
|
z8rvcq0X07zY6u/nIQCfld8Q5CmALCu/69T+ZPKPvfLbJf01OQiAd/prshWA+yWn6bFWfkWmv2vpZxLy
|
||||||
|
BeC78huCTAUwTe6XnKam5MqvCekC4J/+mvwEILDy22nBjx9/FG+wP/E4xUl/jWwBSEh/jf5Y2VQAR6id
|
||||||
|
2F9RPytNf6m5ACRVfj2k/ztniT65G2e4X/ozuvuzX6IvOqR/9/kX2QLgVvrxSU/93Il1Z40EIDD9O1d+
|
||||||
|
Ywrg6Uv0/duX6BnjjZpUfk1IFgC/0o9PesRWALIqvyvVTfPqOS6V35gC+IVztPD+NcvnuCaVXxNyBZBz
|
||||||
|
+mt6xFEAAiu/Ov2Ny0K5VH5jCkChewobE/+1TelnElIFkHf6a3rEUgCFVn6ZCcDf/ItEAfCs/PqmR9wE
|
||||||
|
UHLll40AfKa/RqIAeFZ+fdMjhgKQc9mv5wU/GAnA77cv0gTAt/Lrmx5xEoDA0o/Xyi8LAbSt/JqQJgC+
|
||||||
|
lV/f9IiZAOSkf4DKLwsBLNf+ryiTJQDOlV/f9IiLAASmv7XyO9dwX7rkArhch/n2RZIAZFz264seMRKA
|
||||||
|
pPS3Vn5nV+lY1XBfuuQCaLvghw05AuBe+fVNjzgIIMfKb5sFP5IKoGvl14QUAZSV/poeMREAKr+UWAA+
|
||||||
|
Sj+TkCGA0tJf0yMWAkDld0AyAfio/JqQIABz+ut5nK9GeQBEt6lF064lPUotAIGln06VXxPJBBAy/TX8
|
||||||
|
BWCr/OrVmxajPIDdPfdi9Q96lFwAhVV+TSQRgK/Krwn+AlipzFuhQwAeOCQAgekfdJffJAJYrsMf3NwF
|
||||||
|
8EC9rnPGMhcE4IHDApCU/g6V3zPrdLHucKBEF8BivRk8/TW8BeBS+YUAPDAiAJX+M+q/sNkYw4ql8jtI
|
||||||
|
/1o9ng67/EYXwHKt5ynCvwPjLAC3yi8E4IFRAcha8CPKLr8JBKDnKmaC3xNfAbgu+AEBeOBTAexVfqPd
|
||||||
|
cWci7fIbVQDP/sEf0nPf/qMo98VVAO6VXwjAAwcCOK6ezJrNxhi2UUdJf01UAXz92iY9fTbOtRccBdCs
|
||||||
|
8gsBeGAggJIX/LARVQAXbxB9ofOQ3eAogGaVXwjAA/sCkFT62ahumZeF8rnLLwTg4WG5CaBp5RcC8ECF
|
||||||
|
yq8ZCMDDw3IRQPPSDwTggUpY+gep/JqAADw8LLsA2pR+IAAPaAFcVE/+k7HusBM7dNuW/ntv/8/6usu3
|
||||||
|
f41e3LlHj0Z5fL+98hp9+WsfRLmvpZNz9C83nopxV899hW69+W1613CT2y2W+4IAPNBqc1BgpU8kpkrd
|
||||||
|
BJ3QP5V6EB3RJ1cv9SACEG93YGClTxAAVyCAISCAMPQJAuAKBDAEBBCGPkEAXIEAhoAAwtAnCIArEMAQ
|
||||||
|
EEAY+gQBcAUCGAICCEOfIACuQABDQABh6BMEwBUIYAgIIAx9ggC4AgEMAQGEoU8QAFcggCEggDD0CQLg
|
||||||
|
CgQwBAQQhj5BAFyBAIaAAMLQJwiAKxDAEBBAGPSyXt9IPYgAaAEspB5ERy6pHxnt12Z8h8i6kvIhIAAA
|
||||||
|
CgYCAKBgIAAACgYCAKBgIAAACgYCAKBgIAAACgYCAKBgIAAACgYCAKBgIAAACgYCAKBgIAAACgYCAKBg
|
||||||
|
IAAACgYCAKBgIAAACgYCAKBgIAAACgYCAKBgIAAACgYCAKBgIAAACgYCAKBgIAAACgYCAKBgIAAACgYC
|
||||||
|
AKBgIAAACgYCAKBgIAAACgYCAKBg/h+1RmVpkPBkawAAAABJRU5ErkJggigAAABAAAAAgAAAAAEAIAAA
|
||||||
|
AAAAAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAA
|
||||||
|
AADvAAAA7wAAAO8AAADvAAAA7wAAAO8AAADvAAAA7wAAAO8AAADvAAAA7wAAAO8AAADvAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3wAAAO8AAADvAAAA7wAAAO8A
|
||||||
|
AADvAAAA7wAAAO8AAADvAAAA7wAAAO8AAADvAAAA7wAAAJ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAACPAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8A
|
||||||
|
AAD/AAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAO8A
|
||||||
|
AAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAACfAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjwAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8A
|
||||||
|
AAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAADvAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8A
|
||||||
|
AAD/AAAAnwAAAAAAAAAAAAAAAAAw/2AAMP9wADD/cAAw/3AAMP9wADD/cAAw/3AAMP9wADD/cAAw/3AA
|
||||||
|
MP9gAAAAAAAAAAAAvUVgAL1HcAC9R3AAvUdwAL1HcAA5FbcAORW3ADkVtwAYCdsAAAD/AAAA/wQCAPNO
|
||||||
|
LgC3Ti4At04uALdOLgC3Ti4At04uALclFgDNAAAA/wAAAP8AAAD/ADlOtwA5TrcAOU63AHuniwC9/3AA
|
||||||
|
u/9AAAAAAAAAAAAAAAAwAAAAgAAAAIAAAACAAAAA7wAAAP8AAAD/AAAArwAAAIAAAACAAAAAgAAAAIAA
|
||||||
|
AACAAAAAgAAAAN8AAAD/AAAA/wAAAM8AAACAAAAAgAAAAIAAMP+AADH//wAx//8AMf//ADH//wAx//8A
|
||||||
|
Mf//ADH//wAx//8AMf//ADH//wAw/1AAAAAAALtGgAC9Rv8AvUb/AL1G/wC9Rv8ADAT/AAAA/wAAAP8A
|
||||||
|
AAD/AAAA/wAAAP8RCgDe/5YA//+WAP//lgD//5YA//+WAP//lgD/n14A/wAAAP8AAAD/AAAA/wAAAP8A
|
||||||
|
AAD/AAAA/wB2n/8Avf//AL7/zwAAAAAAAAAAAAAAYAAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAHAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/ADD/IAAx/+8A
|
||||||
|
Mf//ADH//wAx//8AMf//ADH//wAx//8AMf//ADH//wAx//8AMf+/AAAAAAC/QBAAvUbvAL1G/wC9Rv8A
|
||||||
|
vUb/AAwE/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAAz/+WAM//lgD//5YA//+WAP//lgD//5YA/59eAP8A
|
||||||
|
AAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8Adp//AL3//wC9//8AvP9QAAAAAAAAAGAAAAD/AAAA/wAAAP8A
|
||||||
|
AAD/AAAA/wAAAP8AAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvwAAAP8AAAD/AAAA/wAAAP8A
|
||||||
|
AAD/AAAA/wAAAAAAMv+PADH//wAx//8AMf//ADH//wAx//8AMf//ADH//wAx//8AMf//ADH//wAw/0AA
|
||||||
|
AAAAALtGgAC9Rv8AvUb/AL1G/wAMBP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAM//lQBg/5YA//+WAP//
|
||||||
|
lgD//5YA//+WAP+fXgD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AHaf/wC9//8Avf//AL3/rwAAAAAA
|
||||||
|
AABgAAAA3wAAAN8AAADfAAAA3wAAAN8AAADfAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL8A
|
||||||
|
AAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAAAADD/MAAx//8AMf//ADH//wAx//8AMf//ADH//wAx//8A
|
||||||
|
Mf//ADH//wAx//8AMv+vAAAAAAC/SCAAvUbvAL1G/wC9Rv8ADAT/AAAA/wAAAP8AAAD/AAAA/wAAAP8A
|
||||||
|
AADP/48AEP+WAN//lgD//5YA//+WAP//lgD/n14A/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wB2n/8A
|
||||||
|
vf//AL3//wC9//8Au/9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAC/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAAAAAAAAAAMv+vADH//wAx//8A
|
||||||
|
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
|
||||||
|
Mf//ADH//wAx//8AMf//ADD/UAAAAAAAu0aAAL1G/wC9Rv8AvUb/AL1G/wC9Rv8AvUb/AL1G/wC9Rv8A
|
||||||
|
u0aAAAAAAP+WAFD/lgD//5YA//+WAP//lgD//5YA//+WAP//lgD//5YAUAAAAAAAu/+AAL3//wC9//8A
|
||||||
|
vf//AL3//wC9//8Avv/PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMP8QADH/7wAx//8A
|
||||||
|
Mf//ADH//wAx//8AMf//ADH//wAx//8AMf//ADH//wAx/78AAAAAAL9AEAC9Ru8AvUb/AL1G/wC9Rv8A
|
||||||
|
vUb/AL1G/wC9Rv8AvUb/AL1G3wC/QBAAAAAA/5YAz/+WAP//lgD//5YA//+WAP//lgD//5YA//+WAL8A
|
||||||
|
AAAAAL//EAC9/+8Avf//AL3//wC9//8Avf//AL3//wC8/1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAw/4AAMf//ADH//wAx//8AMf//ADH//wAx//8AMf//ADH//wAx//8AMf//ADD/QAAAAAAA
|
||||||
|
u0aAAL1G/wC9Rv8AvUb/AL1G/wC9Rv8AvUb/AL1G/wC9Rv8AvUVgAAAAAP+WAFD/lgD//5YA//+WAP//
|
||||||
|
lgD//5YA//+WAP//lgD//5MAQAAAAAAAu/+AAL3//wC9//8Avf//AL3//wC9//8Avv+/AAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMP8gADH/7wAx//8AMf//ADH//wAx//8AMf//ADH//wAx//8A
|
||||||
|
Mf//ADH//wAy/68AAAAAAL9AEAC9Ru8AvUb/AL1G/wC9Rv8AvUb/AL1G/wC9Rv8AvUb/AL5GzwAAAAD/
|
||||||
|
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
|
||||||
|
Mf/fADH/3wAw/1AAAAAAALxGUAC9Rt8AvUbfAL1G3wC9Rt8AvUbfAL1G3wC9Rt8AvUbfAL1FYAAAAAD/
|
||||||
|
kwBA/5YA3/+WAN//lgDf/5YA3/+WAN//lgDf/5YA3/+TAEAAAAAAAL3/YAC9/98Avf/fAL3/3wC9/98A
|
||||||
|
vf/fAL7/vwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////////////////////////////////////
|
||||||
|
////////////////////////////////////////////+AAf/gAH///4AB/+AAf///gAH/4ABwAYAAAA
|
||||||
|
YAAAAAgAAABgH4AACAAAACAfgIAEAAAAIB+AgAQAAAAf/4DAAgBAAB//gMACAEAAD/+A4AEAIAAP+ADg
|
||||||
|
AQAgAAf4B/AAgBAAB/gH8ACAEAADwAf4AEAIAAPAP/gAQAgAAcA/+AAgBAABwD/8ACAEAQAAf/wAIAIB
|
||||||
|
AAP//gAQAgCAA//+ABAAAIAD//8ACAAAQB///wAIAABAH///gAQAACAfgP+ABAAAIB+A/8ACAAAAH4D/
|
||||||
|
wAIAAAAPgP/gAQAAAAAA/+ABAAAIAAf/8ACAAAQAB//wAIAABAAH//AAQAgCA///+ABACAIB///4AEAE
|
||||||
|
AgH///wAIAQBAf///AAgAgEA///+ABACAID///4AEAIAgH///wAIAQBAf///AAgBAEA///+ABACAID//
|
||||||
|
/4AEAIAgH///wAIAQBAf///AAgBAEA///+ABACAID///4AEAIAgH///gAIAQBAf///AAgBAEB///////
|
||||||
|
//////////////////////////////////////////////////////////////////////////////8o
|
||||||
|
AAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN8A
|
||||||
|
AADvAAAA7wAAAO8AAADvAAAA7wAAAO8AAADvAAAA7wAAAO8AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAACfAAAA7wAAAO8AAADvAAAA7wAAAO8AAADvAAAA7wAAAO8AAADvAAAAgAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAO8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAABAAAAAAAAAAAAA
|
||||||
|
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
|
||||||
|
AAAAAAAAAAAw/yAAMf/vADH//wAx//8AMf//ADH//wAx//8AMf//ADH/7wAw/xAAvEZQAL1G/wC9Rv8A
|
||||||
|
vUb/AL1G/wC9Rv8AgjD/AAAA/wAAAP8AAAD/AAAA/zAcAP//lgD//5YA//+WAK8AAABAAAAA/wAAAP8A
|
||||||
|
AAD/AAAA/wAjMP8Auv8wAAAAAAAAAAAAAAAAAAAAEAAAAP8AAAD/AAAA/wAAAP8AAAD/AAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMv+fADH//wAx//8AMf//ADH//wAx//8AMf//ADH//wAw/4AA
|
||||||
|
AAAAAL5FvwC9Rv8AvUb/AL1G/wC9Rv8AgjD/AAAA/wAAAP8AAAD/AAAA/zAcAP//lgD//5YA//+WAP+i
|
||||||
|
XQBYABsjggBoi/YAL0D/AAAA/wAYIP8APlTVAAAAjwAAAI8AAACPAAAAjwAAAP8AAAD/AAAAvwAAAHAA
|
||||||
|
AABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMP8wADH//wAx//8AMf//ADH//wAx//8A
|
||||||
|
Mf//ADH//wAx/+8AMP8QALxGUAC9Rv8AvUb/AL1G/wC9Rv8AgjD/AAAA/wAAAP8AAAD/AAAA/zAcAP//
|
||||||
|
lgD//5YA//+WAP//lgCvAAAAAAC9/58AO1D/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8A
|
||||||
|
AAD/AAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADL/rwAx//8A
|
||||||
|
Mf//ADH//wAx//8AMf//ADH//wAx//8AMP+AAL9AEAC9Rt8AvUb/AL1G/wC9Rv8AgjD/AAAA/wAAAP8A
|
||||||
|
AAD/AAAA/zAcAP//lgD//5YA//+WAP//lgD//5UAMAC6/zAAO1D/AAAA/wAAAP8AAAD/AAAA/wAAAP8A
|
||||||
|
AAD/AAAA/wAAAP8AAAD/AAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAADD/QAAx//8AMf//ADH//wAx//8AMf//ADH//wAx//8AMf/fADD/EAC7RoAAvUb/AL1G/wC9Rv8A
|
||||||
|
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
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAA////////AAD///////8AAP///////wAA////////AAD///////8AAP//////
|
||||||
|
/wAA//8AH+ADAAD//wAf4AMAAAAAAAEAAAAAAEAAAQPAAAAAAAAAA8AAAIAgAAADwAAAgAAAAH/AAADA
|
||||||
|
ABAAfwAAAMAAAAA/AwAA4AAIAD8DAADgCAAAGAMAAPAABAAYHwAA8AQABAAfAADwAAIAAH8AAPgCAAAA
|
||||||
|
fwAA+AAAAAB/AAD8AQAAA/8AAPwAAAED4AAA/gCAAAPAAAD+AAAAAcAAAP8AQAAAAAAA/wAAAEADAAD/
|
||||||
|
gAAAAAMAAP+AAAAgfwAA/8AAEAB/AAD/wBAAED8AAP/gAAgAPwAA/+AIAAgfAAD/4AAEAB8AAP/wBAAA
|
||||||
|
HwAA//AAAgAPAAD/+AIAAA8AAP/4AAECBwAA//wBAAAHAAD//AAAAQMAAP/+AICAAwAA////////AAD/
|
||||||
|
//////8AAP///////wAA////////AAD///////8AAP///////wAAKAAAACgAAABQAAAAAQAgAAAAAABA
|
||||||
|
GgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI8AAADvAAAA7wAAAO8AAADvAAAA7wAAAO8A
|
||||||
|
AADvAAAA3wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAA7wAAAO8AAADvAAAA7wAAAO8A
|
||||||
|
AADvAAAA7wAAAN8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAACfAAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAN8AAAAAAAAAAAAAAAAA
|
||||||
|
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
|
||||||
|
vf//AL3/7wC//yAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAy/68AMf//ADH//wAx//8AMf//ADH//wAx/+8AMP8gALtGgAC9Rv8AvUb/AL1G/wC9Rv8A
|
||||||
|
vUbvAL9AEP+VAID/lgD//5YA//+WAP//lgD//5MAQAC9/3AAvf//AL3//wC9//8Au/+AAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMP9AADH/7wAx/+8A
|
||||||
|
Mf/vADH/7wAx/+8AMf/vADD/cAC/QBAAvUbvAL1G7wC9Ru8AvUbvAL1G7wC9R3D/lwAg/5YA7/+WAO//
|
||||||
|
lgDv/5YA7/+XAJ8Av/8QAL3/3wC9/+8Avf/vAL3/3wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/
|
||||||
|
/////wAAAP//////AAAA//////8AAAD//////wAAAP//////AAAA//gD+AMAAAD/+AP4AwAAAAAAACAA
|
||||||
|
AAAAAAAAIOAAAAAAgAAA4AAAAIAAAB/gAAAAgECAD4AAAADAAAAPgwAAAMAgAAYDAAAA4AAABg8AAADg
|
||||||
|
AACADwAAAPAAAAA/AAAA8AAAAD8AAAD4AAAA/wAAAPgAAADwAAAA/AAAAOAAAAD8AAAAYAAAAP4AAAAD
|
||||||
|
AAAA/gAAAAMAAAD+AAAAAwAAAP8AAAA/AAAA/wCBAB8AAAD/gAAAHwAAAP+AQAIPAAAA/8AAAA8AAAD/
|
||||||
|
wAABBwAAAP/gAAAHAAAA/+AAAAMAAAD/8AAAAwAAAP/wAAADAAAA//////8AAAD//////wAAAP//////
|
||||||
|
AAAA//////8AAAD//////wAAACgAAAAgAAAAQAAAAAEAIAAAAAAAgBAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
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
|
||||||
|
ukUw/5YAv/+WAO//lgDv/5YA3/+PABAAvv+/AL3/7wC9/+8AvP9QAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAA///////////////////////APgECAAQAAAAAMAAAADCAAAPwgAABwMAAAYHA
|
||||||
|
AACH4AAAB+AAAB/gAAAf8AAAOPAAADD4AAAA+AAAAfwAAAH8AAAP/gAAD/4AAAf/AAAH/wAAA/+AAAP/
|
||||||
|
gAAB/8AAAf////////////////////8oAAAAGAAAADAAAAABACAAAAAAAGAJAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
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
|
||||||
|
lgD//5UAgAC7/4AAvf//AL7/vwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAx/88A
|
||||||
|
Mf//ADH//wAx//8ATddMAL1G7wC9Rv8AvUb/AL1FYP+WAL//lgD//5YA73eqiDwAvf/vAL3//wC7/0AA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAw/2AAMf/vADH/7wAx/+8AMv+fALtGgAC9Ru8A
|
||||||
|
vUbvAL5Fv/+WAFD/lgDv/5YA7/+WAHAAvf+fAL3/7wC9/58AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wD///8A/wOBAAAAAAAAABgAAABwAIAAcQCA
|
||||||
|
AAEAwAADAMAABwDgABwA4AAIAPAAAADwAAEA+AAHAPgABwD8AAMA/AADAP4AAQD+AAEA////AP///wD/
|
||||||
|
//8AKAAAABQAAAAoAAAAAQAgAAAAAACQBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAgAAAAIAA
|
||||||
|
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
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
|
@ -1,191 +1,20 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using System.Configuration;
|
|
||||||
|
|
||||||
namespace WelsonJS.Launcher
|
namespace WelsonJS.Launcher
|
||||||
{
|
{
|
||||||
internal static class Program
|
internal static class Program
|
||||||
{
|
{
|
||||||
static Mutex mutex;
|
/// <summary>
|
||||||
public static ResourceServer resourceServer;
|
/// 해당 애플리케이션의 주 진입점입니다.
|
||||||
|
/// </summary>
|
||||||
[STAThread]
|
[STAThread]
|
||||||
static void Main()
|
static void Main()
|
||||||
{
|
{
|
||||||
mutex = new Mutex(true, "WelsonJS.Launcher.Mutex", out bool isMutexNotExists);
|
|
||||||
if (!isMutexNotExists)
|
|
||||||
{
|
|
||||||
MessageBox.Show("WelsonJS Launcher already running.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Application.EnableVisualStyles();
|
Application.EnableVisualStyles();
|
||||||
Application.SetCompatibleTextRenderingDefault(false);
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
Application.Run(new MainForm());
|
Application.Run(new MainForm());
|
||||||
|
|
||||||
mutex.ReleaseMutex();
|
|
||||||
mutex.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void RunCommandPrompt(string workingDirectory, string entryFileName, string scriptName, bool isConsoleApplication = false, bool isInteractiveServiceAapplication = false)
|
|
||||||
{
|
|
||||||
if (!isConsoleApplication)
|
|
||||||
{
|
|
||||||
if (!File.Exists(Path.Combine(workingDirectory, entryFileName)))
|
|
||||||
{
|
|
||||||
throw new Exception("Not Found: " + entryFileName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!Directory.EnumerateFiles(workingDirectory, scriptName + ".*").Any())
|
|
||||||
{
|
|
||||||
throw new Exception("Not found matches file: " + scriptName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Process process = new Process
|
|
||||||
{
|
|
||||||
StartInfo = new ProcessStartInfo("cmd")
|
|
||||||
{
|
|
||||||
UseShellExecute = false,
|
|
||||||
RedirectStandardInput = true,
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
CreateNoWindow = true,
|
|
||||||
Arguments = "/k",
|
|
||||||
}
|
|
||||||
};
|
|
||||||
process.Start();
|
|
||||||
|
|
||||||
process.StandardInput.WriteLine("pushd " + workingDirectory);
|
|
||||||
process.StandardInput.WriteLine();
|
|
||||||
process.StandardInput.Flush();
|
|
||||||
process.StandardOutput.ReadLine();
|
|
||||||
|
|
||||||
if (isInteractiveServiceAapplication)
|
|
||||||
{
|
|
||||||
process.StandardInput.WriteLine($"start cmd /c startInteractiveService.bat");
|
|
||||||
process.StandardInput.WriteLine();
|
|
||||||
process.StandardInput.Flush();
|
|
||||||
process.StandardOutput.ReadLine();
|
|
||||||
}
|
|
||||||
else if (!isConsoleApplication)
|
|
||||||
{
|
|
||||||
process.StandardInput.WriteLine(entryFileName);
|
|
||||||
process.StandardInput.WriteLine();
|
|
||||||
process.StandardInput.Flush();
|
|
||||||
process.StandardOutput.ReadLine();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
process.StandardInput.WriteLine($"start cmd /c cscript app.js {scriptName}");
|
|
||||||
process.StandardInput.WriteLine();
|
|
||||||
process.StandardInput.Flush();
|
|
||||||
process.StandardOutput.ReadLine();
|
|
||||||
}
|
|
||||||
process.StandardInput.Close();
|
|
||||||
process.WaitForExit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetFinalDirectory(string path)
|
|
||||||
{
|
|
||||||
string[] directories = Directory.GetDirectories(path);
|
|
||||||
|
|
||||||
while (directories.Length == 1)
|
|
||||||
{
|
|
||||||
path = directories[0];
|
|
||||||
directories = Directory.GetDirectories(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetAppDataPath()
|
|
||||||
{
|
|
||||||
string path = Path.Combine(
|
|
||||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
|
||||||
"WelsonJS"
|
|
||||||
);
|
|
||||||
|
|
||||||
Directory.CreateDirectory(path);
|
|
||||||
|
|
||||||
if (!Directory.Exists(path))
|
|
||||||
{
|
|
||||||
throw new IOException("Failed to create directory: " + path);
|
|
||||||
}
|
|
||||||
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetWorkingDirectory(string instanceId, bool followSubDirectory = false)
|
|
||||||
{
|
|
||||||
string workingDirectory = Path.Combine(GetAppDataPath(), instanceId);
|
|
||||||
|
|
||||||
if (followSubDirectory)
|
|
||||||
{
|
|
||||||
if (!Directory.Exists(workingDirectory))
|
|
||||||
{
|
|
||||||
workingDirectory = Path.Combine(Path.GetTempPath(), instanceId);
|
|
||||||
}
|
|
||||||
|
|
||||||
workingDirectory = GetFinalDirectory(workingDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
return workingDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void StartResourceServer()
|
|
||||||
{
|
|
||||||
lock(typeof(Program))
|
|
||||||
{
|
|
||||||
if (resourceServer == null)
|
|
||||||
{
|
|
||||||
resourceServer = new ResourceServer(GetAppConfig("ResourceServerPrefix"), "editor.html");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static void OpenWebBrowser(string url)
|
|
||||||
{
|
|
||||||
Uri resourceServerUri = new Uri(GetAppConfig("ResourceServerPrefix"));
|
|
||||||
Uri devToolsUri = new Uri(GetAppConfig("DevToolsPrefix"));
|
|
||||||
|
|
||||||
string userDataDir = Path.Combine(GetAppDataPath(), "EdgeUserProfile");
|
|
||||||
string remoteAllowOrigins = $"{resourceServerUri.Scheme}://{resourceServerUri.Host}:{resourceServerUri.Port}";
|
|
||||||
int remoteDebuggingPort = devToolsUri.Port;
|
|
||||||
string[] arguments = {
|
|
||||||
$"\"{url}\"",
|
|
||||||
$"--remote-debugging-port={remoteDebuggingPort}",
|
|
||||||
$"--remote-allow-origins={remoteAllowOrigins}", // for security reason
|
|
||||||
$"--user-data-dir=\"{userDataDir}\""
|
|
||||||
};
|
|
||||||
|
|
||||||
Process.Start(new ProcessStartInfo
|
|
||||||
{
|
|
||||||
FileName = "msedge.exe",
|
|
||||||
Arguments = string.Join(" ", arguments),
|
|
||||||
UseShellExecute = true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string GetAppConfig(string key)
|
|
||||||
{
|
|
||||||
string value = ConfigurationManager.AppSettings[key];
|
|
||||||
if (!string.IsNullOrEmpty(value))
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = Properties.Resources.ResourceManager.GetString(key);
|
|
||||||
if (!string.IsNullOrEmpty(value))
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,11 @@ using System.Runtime.InteropServices;
|
||||||
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
|
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
|
||||||
// 이러한 특성 값을 변경하세요.
|
// 이러한 특성 값을 변경하세요.
|
||||||
[assembly: AssemblyTitle("WelsonJS.Launcher")]
|
[assembly: AssemblyTitle("WelsonJS.Launcher")]
|
||||||
[assembly: AssemblyDescription("Launcher for WelsonJS Application Packages")]
|
[assembly: AssemblyDescription("Launcher for WelsonJS Application Package")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("Catswords")]
|
[assembly: AssemblyCompany("Catswords")]
|
||||||
[assembly: AssemblyProduct("WelsonJS")]
|
[assembly: AssemblyProduct("WelsonJS")]
|
||||||
[assembly: AssemblyCopyright("Catswords OSS, GPLv3 or Ms-RL")]
|
[assembly: AssemblyCopyright("Catswords OSS, C-2021-000237, Opensource licensed under GPLv3 or MS-RL")]
|
||||||
[assembly: AssemblyTrademark("WelsonJS")]
|
[assembly: AssemblyTrademark("WelsonJS")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||||
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
|
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
|
||||||
// 기본값으로 할 수 있습니다.
|
// 기본값으로 할 수 있습니다.
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("0.2.7.54")]
|
[assembly: AssemblyVersion("0.2.7.31")]
|
||||||
[assembly: AssemblyFileVersion("0.2.7.54")]
|
[assembly: AssemblyFileVersion("0.2.7.31")]
|
||||||
|
|
|
@ -60,175 +60,6 @@ namespace WelsonJS.Launcher.Properties {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 과(와) 유사한 지역화된 문자열을 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static string AzureAiServiceApiKey {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("AzureAiServiceApiKey", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 2024-05-01-preview과(와) 유사한 지역화된 문자열을 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static string AzureAiServiceApiVersion {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("AzureAiServiceApiVersion", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// https://ai-catswords656881030318.services.ai.azure.com/과(와) 유사한 지역화된 문자열을 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static string AzureAiServicePrefix {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("AzureAiServicePrefix", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// https://catswords.blob.core.windows.net/welsonjs/blob.config.xml과(와) 유사한 지역화된 문자열을 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static string BlobConfigUrl {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("BlobConfigUrl", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// https://catswords.blob.core.windows.net/welsonjs/과(와) 유사한 지역화된 문자열을 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static string BlobStoragePrefix {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("BlobStoragePrefix", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 과(와) 유사한 지역화된 문자열을 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static string CitiApiKey {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("CitiApiKey", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// https://api.criminalip.io/v1/과(와) 유사한 지역화된 문자열을 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static string CitiApiPrefix {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("CitiApiPrefix", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// https://copilot.microsoft.com/과(와) 유사한 지역화된 문자열을 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static string CopilotUrl {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("CopilotUrl", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// http://localhost:9222/과(와) 유사한 지역화된 문자열을 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static string DevToolsPrefix {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("DevToolsPrefix", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 1.1.1.1과(와) 유사한 지역화된 문자열을 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static string DnsServerAddress {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("DnsServerAddress", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// (아이콘)과(와) 유사한 System.Drawing.Icon 형식의 지역화된 리소스를 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static System.Drawing.Icon favicon {
|
|
||||||
get {
|
|
||||||
object obj = ResourceManager.GetObject("favicon", resourceCulture);
|
|
||||||
return ((System.Drawing.Icon)(obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 90과(와) 유사한 지역화된 문자열을 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static string HttpClientTimeout {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("HttpClientTimeout", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static System.Drawing.Bitmap icon_check_32 {
|
|
||||||
get {
|
|
||||||
object obj = ResourceManager.GetObject("icon_check_32", resourceCulture);
|
|
||||||
return ((System.Drawing.Bitmap)(obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static System.Drawing.Bitmap icon_delete_32 {
|
|
||||||
get {
|
|
||||||
object obj = ResourceManager.GetObject("icon_delete_32", resourceCulture);
|
|
||||||
return ((System.Drawing.Bitmap)(obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static System.Drawing.Bitmap icon_directory_32 {
|
|
||||||
get {
|
|
||||||
object obj = ResourceManager.GetObject("icon_directory_32", resourceCulture);
|
|
||||||
return ((System.Drawing.Bitmap)(obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static System.Drawing.Bitmap icon_export_32 {
|
|
||||||
get {
|
|
||||||
object obj = ResourceManager.GetObject("icon_export_32", resourceCulture);
|
|
||||||
return ((System.Drawing.Bitmap)(obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static System.Drawing.Bitmap icon_file_32 {
|
|
||||||
get {
|
|
||||||
object obj = ResourceManager.GetObject("icon_file_32", resourceCulture);
|
|
||||||
return ((System.Drawing.Bitmap)(obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static System.Drawing.Bitmap icon_import_32 {
|
|
||||||
get {
|
|
||||||
object obj = ResourceManager.GetObject("icon_import_32", resourceCulture);
|
|
||||||
return ((System.Drawing.Bitmap)(obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다.
|
/// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -239,16 +70,6 @@ namespace WelsonJS.Launcher.Properties {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static System.Drawing.Bitmap icon_start_32 {
|
|
||||||
get {
|
|
||||||
object obj = ResourceManager.GetObject("icon_start_32", resourceCulture);
|
|
||||||
return ((System.Drawing.Bitmap)(obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다.
|
/// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -258,50 +79,5 @@ namespace WelsonJS.Launcher.Properties {
|
||||||
return ((System.Drawing.Bitmap)(obj));
|
return ((System.Drawing.Bitmap)(obj));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// https://github.com/gnh1201/welsonjs과(와) 유사한 지역화된 문자열을 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static string RepositoryUrl {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("RepositoryUrl", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// http://localhost:3000/과(와) 유사한 지역화된 문자열을 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static string ResourceServerPrefix {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("ResourceServerPrefix", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 141.101.82.1과(와) 유사한 지역화된 문자열을 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static string WhoisClientAddress {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("WhoisClientAddress", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// https://xn--c79as89aj0e29b77z.xn--3e0b707e/kor/whois/whois.jsp과(와) 유사한 지역화된 문자열을 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static string WhoisReferrerUrl {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("WhoisReferrerUrl", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// https://xn--c79as89aj0e29b77z.xn--3e0b707e/kor/whois.jsc과(와) 유사한 지역화된 문자열을 찾습니다.
|
|
||||||
/// </summary>
|
|
||||||
internal static string WhoisServerUrl {
|
|
||||||
get {
|
|
||||||
return ResourceManager.GetString("WhoisServerUrl", resourceCulture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,88 +112,16 @@
|
||||||
<value>2.0</value>
|
<value>2.0</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<resheader name="reader">
|
<resheader name="reader">
|
||||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||||
<data name="icon_link_128" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="icon_link_128" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\icon_link_128.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
<value>..\Resources\icon_link_128.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="icon_zip_128" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="icon_zip_128" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\icon_zip_128.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
<value>..\Resources\icon_zip_128.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="favicon" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\Resources\favicon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
|
||||||
</data>
|
|
||||||
<data name="icon_directory_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\Resources\icon_directory_32.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
|
||||||
</data>
|
|
||||||
<data name="icon_file_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\Resources\icon_file_32.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
|
||||||
</data>
|
|
||||||
<data name="icon_check_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\Resources\icon_check_32.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
|
||||||
</data>
|
|
||||||
<data name="icon_export_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\Resources\icon_export_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
|
||||||
</data>
|
|
||||||
<data name="icon_import_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\Resources\icon_import_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
|
||||||
</data>
|
|
||||||
<data name="icon_delete_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\Resources\icon_delete_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
|
||||||
</data>
|
|
||||||
<data name="icon_start_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
|
||||||
<value>..\Resources\icon_start_32.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
|
||||||
</data>
|
|
||||||
<data name="CopilotUrl" xml:space="preserve">
|
|
||||||
<value>https://copilot.microsoft.com/</value>
|
|
||||||
</data>
|
|
||||||
<data name="RepositoryUrl" xml:space="preserve">
|
|
||||||
<value>https://github.com/gnh1201/welsonjs</value>
|
|
||||||
</data>
|
|
||||||
<data name="ResourceServerPrefix" xml:space="preserve">
|
|
||||||
<value>http://localhost:3000/</value>
|
|
||||||
</data>
|
|
||||||
<data name="DevToolsPrefix" xml:space="preserve">
|
|
||||||
<value>http://localhost:9222/</value>
|
|
||||||
</data>
|
|
||||||
<data name="AzureAiServiceApiKey" xml:space="preserve">
|
|
||||||
<value />
|
|
||||||
</data>
|
|
||||||
<data name="AzureAiServicePrefix" xml:space="preserve">
|
|
||||||
<value>https://ai-catswords656881030318.services.ai.azure.com/</value>
|
|
||||||
</data>
|
|
||||||
<data name="DnsServerAddress" xml:space="preserve">
|
|
||||||
<value>1.1.1.1</value>
|
|
||||||
</data>
|
|
||||||
<data name="WhoisClientAddress" xml:space="preserve">
|
|
||||||
<value>141.101.82.1</value>
|
|
||||||
</data>
|
|
||||||
<data name="WhoisReferrerUrl" xml:space="preserve">
|
|
||||||
<value>https://xn--c79as89aj0e29b77z.xn--3e0b707e/kor/whois/whois.jsp</value>
|
|
||||||
</data>
|
|
||||||
<data name="WhoisServerUrl" xml:space="preserve">
|
|
||||||
<value>https://xn--c79as89aj0e29b77z.xn--3e0b707e/kor/whois.jsc</value>
|
|
||||||
</data>
|
|
||||||
<data name="BlobStoragePrefix" xml:space="preserve">
|
|
||||||
<value>https://catswords.blob.core.windows.net/welsonjs/</value>
|
|
||||||
</data>
|
|
||||||
<data name="AzureAiServiceApiVersion" xml:space="preserve">
|
|
||||||
<value>2024-05-01-preview</value>
|
|
||||||
</data>
|
|
||||||
<data name="BlobConfigUrl" xml:space="preserve">
|
|
||||||
<value>https://catswords.blob.core.windows.net/welsonjs/blob.config.xml</value>
|
|
||||||
</data>
|
|
||||||
<data name="HttpClientTimeout" xml:space="preserve">
|
|
||||||
<value>90</value>
|
|
||||||
</data>
|
|
||||||
<data name="CitiApiKey" xml:space="preserve">
|
|
||||||
<value />
|
|
||||||
</data>
|
|
||||||
<data name="CitiApiPrefix" xml:space="preserve">
|
|
||||||
<value>https://api.criminalip.io/v1/</value>
|
|
||||||
</data>
|
|
||||||
</root>
|
</root>
|
|
@ -1,506 +0,0 @@
|
||||||
// ResourceServer.cs
|
|
||||||
// A resource server of WelsonJS Editor (WelsonJS.Launcher)
|
|
||||||
// Namhyeon Go <abuse@catswords.net>
|
|
||||||
// https://github.com/gnh1201/welsonjs
|
|
||||||
//
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using System.Xml.Serialization;
|
|
||||||
|
|
||||||
namespace WelsonJS.Launcher
|
|
||||||
{
|
|
||||||
public class ResourceServer
|
|
||||||
{
|
|
||||||
private readonly HttpListener _listener;
|
|
||||||
private CancellationTokenSource _cts;
|
|
||||||
private Task _serverTask;
|
|
||||||
private bool _isRunning;
|
|
||||||
private string _prefix;
|
|
||||||
private string _resourceName;
|
|
||||||
private List<IResourceTool> _tools = new List<IResourceTool>();
|
|
||||||
private static readonly HttpClient _httpClient = new HttpClient();
|
|
||||||
private static readonly string _defaultMimeType = "application/octet-stream";
|
|
||||||
private static BlobConfig _blobConfig;
|
|
||||||
|
|
||||||
static ResourceServer()
|
|
||||||
{
|
|
||||||
// Set timeout
|
|
||||||
int timeout = int.TryParse(Program.GetAppConfig("HttpClientTimeout"), out timeout) ? timeout : 90;
|
|
||||||
_httpClient.Timeout = TimeSpan.FromSeconds(timeout);
|
|
||||||
|
|
||||||
// Fetch a blob config from Internet
|
|
||||||
FetchBlobConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResourceServer(string prefix, string resourceName)
|
|
||||||
{
|
|
||||||
_prefix = prefix;
|
|
||||||
_listener = new HttpListener();
|
|
||||||
_listener.Prefixes.Add(prefix);
|
|
||||||
_resourceName = resourceName;
|
|
||||||
|
|
||||||
// Add resource tools
|
|
||||||
_tools.Add(new ResourceTools.Completion(this, _httpClient));
|
|
||||||
_tools.Add(new ResourceTools.Settings(this, _httpClient));
|
|
||||||
_tools.Add(new ResourceTools.DevTools(this, _httpClient));
|
|
||||||
_tools.Add(new ResourceTools.DnsQuery(this, _httpClient));
|
|
||||||
_tools.Add(new ResourceTools.CitiQuery(this, _httpClient));
|
|
||||||
_tools.Add(new ResourceTools.Tfa(this, _httpClient));
|
|
||||||
_tools.Add(new ResourceTools.Whois(this, _httpClient));
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetPrefix()
|
|
||||||
{
|
|
||||||
return _prefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Start()
|
|
||||||
{
|
|
||||||
if (_isRunning) return;
|
|
||||||
|
|
||||||
_isRunning = true;
|
|
||||||
_cts = new CancellationTokenSource();
|
|
||||||
_listener.Start();
|
|
||||||
|
|
||||||
// Open the web browser
|
|
||||||
Program.OpenWebBrowser(_prefix);
|
|
||||||
|
|
||||||
// Run a task with cancellation token
|
|
||||||
_serverTask = Task.Run(() => ListenLoop(_cts.Token));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Stop()
|
|
||||||
{
|
|
||||||
_isRunning = false;
|
|
||||||
_cts.Cancel();
|
|
||||||
_listener.Stop();
|
|
||||||
|
|
||||||
MessageBox.Show("Server stopped.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsRunning()
|
|
||||||
{
|
|
||||||
return _isRunning;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ListenLoop(CancellationToken token)
|
|
||||||
{
|
|
||||||
while (!token.IsCancellationRequested && _isRunning)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await ProcessRequest(await _listener.GetContextAsync());
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
if (token.IsCancellationRequested || !_isRunning) break;
|
|
||||||
MessageBox.Show($"Error: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ProcessRequest(HttpListenerContext context)
|
|
||||||
{
|
|
||||||
string path = context.Request.Url.AbsolutePath.TrimStart('/');
|
|
||||||
|
|
||||||
// Serve from a resource name
|
|
||||||
if (String.IsNullOrEmpty(path))
|
|
||||||
{
|
|
||||||
ServeResource(context, GetResource(_resourceName), "text/html");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serve the favicon.ico file
|
|
||||||
if ("favicon.ico".Equals(path, StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
ServeResource(context, GetResource("favicon"), "image/x-icon");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serve from a resource tool
|
|
||||||
foreach (var tool in _tools)
|
|
||||||
{
|
|
||||||
if (tool.CanHandle(path))
|
|
||||||
{
|
|
||||||
await tool.HandleAsync(context, path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serve from the blob server
|
|
||||||
if (await ServeBlob(context, path)) return;
|
|
||||||
|
|
||||||
// Fallback to serve from a resource name
|
|
||||||
ServeResource(context, GetResource(_resourceName), "text/html");
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<bool> ServeBlob(HttpListenerContext context, string path, string prefix = null)
|
|
||||||
{
|
|
||||||
byte[] data;
|
|
||||||
string mimeType;
|
|
||||||
|
|
||||||
if (!String.IsNullOrEmpty(prefix))
|
|
||||||
{
|
|
||||||
string url = $"{prefix}{path}";
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (var client = new HttpClient())
|
|
||||||
{
|
|
||||||
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, url);
|
|
||||||
request.Headers.UserAgent.ParseAdd(context.Request.UserAgent);
|
|
||||||
HttpResponseMessage response = await client.SendAsync(request);
|
|
||||||
|
|
||||||
if (!response.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
Trace.TraceError($"Failed to serve blob. URL: {url}, Status: {response.StatusCode}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = await response.Content.ReadAsByteArrayAsync();
|
|
||||||
mimeType = response.Content.Headers.ContentType?.MediaType ?? _defaultMimeType;
|
|
||||||
|
|
||||||
ServeResource(context, data, mimeType);
|
|
||||||
_ = TrySaveCachedBlob(path, data, mimeType);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Trace.TraceError($"Failed to serve blob. URL: {url}, Exception: {ex.Message}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// use the cached data
|
|
||||||
if (TryGetCachedBlob(path, out mimeType, true))
|
|
||||||
{
|
|
||||||
if (TryGetCachedBlob(path, out data))
|
|
||||||
{
|
|
||||||
if (String.IsNullOrEmpty(mimeType))
|
|
||||||
{
|
|
||||||
mimeType = _defaultMimeType;
|
|
||||||
}
|
|
||||||
|
|
||||||
ServeResource(context, data, mimeType);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// use a blob source
|
|
||||||
if (await TryServeFromBlob(context, path))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<bool> TryServeFromBlob(HttpListenerContext context, string path)
|
|
||||||
{
|
|
||||||
if (_blobConfig != null)
|
|
||||||
{
|
|
||||||
foreach (var route in _blobConfig.Routes)
|
|
||||||
{
|
|
||||||
foreach (var (regex, index) in route.RegexConditions.Select((r, i) => (r, i)))
|
|
||||||
{
|
|
||||||
if (!regex.Compiled.IsMatch(path)) continue;
|
|
||||||
|
|
||||||
var match = (index < route.Matches.Count) ? route.Matches[index] : route.Matches.First();
|
|
||||||
var _path = route.StripPrefix ? path.Substring(match.Length) : path;
|
|
||||||
|
|
||||||
foreach (var prefixUrl in route.PrefixUrls)
|
|
||||||
{
|
|
||||||
if (await ServeBlob(context, _path, prefixUrl))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fallback
|
|
||||||
string prefix = Program.GetAppConfig("BlobStoragePrefix");
|
|
||||||
if (await ServeBlob(context, path, prefix))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetCachedBlobPath(string path)
|
|
||||||
{
|
|
||||||
// Get a hash from the path
|
|
||||||
string hashedPath;
|
|
||||||
using (MD5 md5 = MD5.Create())
|
|
||||||
{
|
|
||||||
byte[] bHashedPath = md5.ComputeHash(Encoding.UTF8.GetBytes(path));
|
|
||||||
hashedPath = BitConverter.ToString(bHashedPath).Replace("-", "").ToLowerInvariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a sub-directory paths from the hashed path
|
|
||||||
string[] subDirectoryPaths = new string[] {
|
|
||||||
hashedPath.Substring(0, 2),
|
|
||||||
hashedPath.Substring(2, 2),
|
|
||||||
hashedPath.Substring(4, 2)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Return the cache path
|
|
||||||
return Path.Combine(Program.GetAppDataPath(), "BlobCache", String.Join("\\", subDirectoryPaths), hashedPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool TryGetCachedBlob(string path, out byte[] data, bool isMetadata = false)
|
|
||||||
{
|
|
||||||
string cachePath = GetCachedBlobPath(path);
|
|
||||||
if (isMetadata)
|
|
||||||
{
|
|
||||||
cachePath = $"{cachePath}.meta";
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (File.Exists(cachePath))
|
|
||||||
{
|
|
||||||
data = File.ReadAllBytes(cachePath);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Trace.TraceError($"Cache Read Error: {ex.Message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
data = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool TryGetCachedBlob(string path, out string data, bool isMetadata = false)
|
|
||||||
{
|
|
||||||
byte[] bData;
|
|
||||||
if (TryGetCachedBlob(path, out bData, isMetadata))
|
|
||||||
{
|
|
||||||
data = Encoding.UTF8.GetString(bData);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<bool> TrySaveCachedBlob(string path, byte[] data, string mimeType)
|
|
||||||
{
|
|
||||||
await Task.Delay(0);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string cachePath = GetCachedBlobPath(path);
|
|
||||||
string cacheDirectory = Path.GetDirectoryName(cachePath);
|
|
||||||
|
|
||||||
// Is exists the cached blob directory
|
|
||||||
if (!Directory.Exists(cacheDirectory))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(cacheDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the cache
|
|
||||||
File.WriteAllBytes(cachePath, data);
|
|
||||||
|
|
||||||
// Save the cache meta
|
|
||||||
File.WriteAllBytes($"{cachePath}.meta", Encoding.UTF8.GetBytes(mimeType));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Trace.TraceError($"Error: {ex.Message}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ServeResource(HttpListenerContext context)
|
|
||||||
{
|
|
||||||
ServeResource(context, "<error>Not Found</error>", "application/xml", 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ServeResource(HttpListenerContext context, byte[] data, string mimeType = "text/html", int statusCode = 200)
|
|
||||||
{
|
|
||||||
string xmlHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
|
|
||||||
|
|
||||||
if (data == null)
|
|
||||||
{
|
|
||||||
data = Encoding.UTF8.GetBytes(xmlHeader + "\r\n<error>Could not find the resource.</error>");
|
|
||||||
mimeType = "application/xml";
|
|
||||||
statusCode = 404;
|
|
||||||
}
|
|
||||||
|
|
||||||
context.Response.StatusCode = statusCode;
|
|
||||||
context.Response.ContentType = mimeType;
|
|
||||||
context.Response.ContentLength64 = data.Length;
|
|
||||||
using (Stream outputStream = context.Response.OutputStream)
|
|
||||||
{
|
|
||||||
outputStream.Write(data, 0, data.Length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ServeResource(HttpListenerContext context, string data, string mimeType = "text/html", int statusCode = 200)
|
|
||||||
{
|
|
||||||
string xmlHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
|
|
||||||
|
|
||||||
if (data == null)
|
|
||||||
{
|
|
||||||
data = xmlHeader + "\r\n<error>Could not find the resource.</error>";
|
|
||||||
mimeType = "application/xml";
|
|
||||||
statusCode = 404;
|
|
||||||
}
|
|
||||||
else if (mimeType == "application/xml" && !data.StartsWith("<?xml"))
|
|
||||||
{
|
|
||||||
data = xmlHeader + "\r\n" + data;
|
|
||||||
}
|
|
||||||
else if (mimeType == "application/json")
|
|
||||||
{
|
|
||||||
data = xmlHeader + "\r\n<json><![CDATA[" + data + "]]></json>";
|
|
||||||
mimeType = "application/xml";
|
|
||||||
}
|
|
||||||
|
|
||||||
ServeResource(context, Encoding.UTF8.GetBytes(data), mimeType, statusCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] GetResource(string resourceName)
|
|
||||||
{
|
|
||||||
// Try to fetch embedded resource.
|
|
||||||
byte[] data = GetEmbeddedResource(typeof(Program).Namespace + "." + resourceName);
|
|
||||||
if (data != null) return data;
|
|
||||||
|
|
||||||
// Fallback: Try to fetch resource from ResourceManager.
|
|
||||||
return GetResourceFromManager(resourceName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] GetEmbeddedResource(string fullResourceName)
|
|
||||||
{
|
|
||||||
Assembly assembly = Assembly.GetExecutingAssembly();
|
|
||||||
using (Stream stream = assembly.GetManifestResourceStream(fullResourceName))
|
|
||||||
{
|
|
||||||
if (stream != null)
|
|
||||||
{
|
|
||||||
using (MemoryStream memoryStream = new MemoryStream())
|
|
||||||
{
|
|
||||||
stream.CopyTo(memoryStream);
|
|
||||||
return memoryStream.ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] GetResourceFromManager(string resourceName)
|
|
||||||
{
|
|
||||||
object resourceObject = Properties.Resources.ResourceManager.GetObject(resourceName);
|
|
||||||
switch (resourceObject)
|
|
||||||
{
|
|
||||||
case byte[] resourceBytes:
|
|
||||||
return resourceBytes;
|
|
||||||
case System.Drawing.Icon icon:
|
|
||||||
return ConvertIconToBytes(icon);
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] ConvertIconToBytes(System.Drawing.Icon icon)
|
|
||||||
{
|
|
||||||
using (MemoryStream memoryStream = new MemoryStream())
|
|
||||||
{
|
|
||||||
icon.Save(memoryStream);
|
|
||||||
return memoryStream.ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async void FetchBlobConfig()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string url = Program.GetAppConfig("BlobConfigUrl");
|
|
||||||
var response = await _httpClient.GetStreamAsync(url);
|
|
||||||
|
|
||||||
var serializer = new XmlSerializer(typeof(BlobConfig));
|
|
||||||
using (var reader = new StreamReader(response))
|
|
||||||
{
|
|
||||||
_blobConfig = (BlobConfig)serializer.Deserialize(reader);
|
|
||||||
}
|
|
||||||
|
|
||||||
_blobConfig?.Compile();
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Trace.TraceError($"Failed to fetch a blob config. Exception: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[XmlRoot("blobConfig")]
|
|
||||||
public class BlobConfig
|
|
||||||
{
|
|
||||||
[XmlArray("routes")]
|
|
||||||
[XmlArrayItem("route")]
|
|
||||||
public List<BlobRoute> Routes { get; set; } = new List<BlobRoute>();
|
|
||||||
|
|
||||||
public void Compile()
|
|
||||||
{
|
|
||||||
foreach (var route in Routes)
|
|
||||||
{
|
|
||||||
if (route.Matches == null) continue;
|
|
||||||
|
|
||||||
route.RegexConditions = new List<RegexCondition>();
|
|
||||||
foreach (var match in route.Matches)
|
|
||||||
{
|
|
||||||
route.RegexConditions.Add(new RegexCondition
|
|
||||||
{
|
|
||||||
Pattern = match,
|
|
||||||
Compiled = new Regex(
|
|
||||||
match.StartsWith("^") ? match : "^" + Regex.Escape(match),
|
|
||||||
RegexOptions.Compiled)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class BlobRoute
|
|
||||||
{
|
|
||||||
[XmlArray("matches")]
|
|
||||||
[XmlArrayItem("match")]
|
|
||||||
public List<string> Matches { get; set; }
|
|
||||||
|
|
||||||
[XmlArray("prefixUrls")]
|
|
||||||
[XmlArrayItem("url")]
|
|
||||||
public List<string> PrefixUrls { get; set; }
|
|
||||||
|
|
||||||
[XmlAttribute("stripPrefix")]
|
|
||||||
public bool StripPrefix { get; set; }
|
|
||||||
|
|
||||||
[XmlIgnore]
|
|
||||||
public List<RegexCondition> RegexConditions { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class RegexCondition
|
|
||||||
{
|
|
||||||
[XmlIgnore]
|
|
||||||
public string Pattern { get; set; }
|
|
||||||
|
|
||||||
[XmlIgnore]
|
|
||||||
public Regex Compiled { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Net;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace WelsonJS.Launcher.ResourceTools
|
|
||||||
{
|
|
||||||
public class CitiQuery : IResourceTool
|
|
||||||
{
|
|
||||||
private readonly ResourceServer Server;
|
|
||||||
private readonly HttpClient _httpClient;
|
|
||||||
private const string Prefix = "citi-query/";
|
|
||||||
|
|
||||||
public CitiQuery(ResourceServer server, HttpClient httpClient)
|
|
||||||
{
|
|
||||||
Server = server;
|
|
||||||
_httpClient = httpClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CanHandle(string path)
|
|
||||||
{
|
|
||||||
return path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task HandleAsync(HttpListenerContext context, string path)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string target = path.Substring(Prefix.Length).Trim();
|
|
||||||
string apiKey = Program.GetAppConfig("CitiApiKey");
|
|
||||||
if (string.IsNullOrEmpty(apiKey))
|
|
||||||
{
|
|
||||||
Server.ServeResource(context, "<error>Missing API key<error>", "application/xml", 500);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string encoded = Uri.EscapeDataString(target);
|
|
||||||
string apiPrefix = Program.GetAppConfig("CitiApiPrefix");
|
|
||||||
string url = $"{apiPrefix}asset/ip/report?ip={encoded}&full=true";
|
|
||||||
|
|
||||||
var request = new HttpRequestMessage(HttpMethod.Get, url);
|
|
||||||
request.Headers.Add("x-api-key", apiKey);
|
|
||||||
request.Headers.Add("User-Agent", context.Request.UserAgent);
|
|
||||||
|
|
||||||
HttpResponseMessage response = await _httpClient.SendAsync(request);
|
|
||||||
string content = await response.Content.ReadAsStringAsync();
|
|
||||||
|
|
||||||
context.Response.StatusCode = (int)response.StatusCode;
|
|
||||||
Server.ServeResource(context, content, "application/json", (int)response.StatusCode);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Server.ServeResource(context, $"<error>{ex.Message}</error>", "application/xml", 500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,214 +0,0 @@
|
||||||
using Microsoft.Win32;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Net;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
|
|
||||||
namespace WelsonJS.Launcher.ResourceTools
|
|
||||||
{
|
|
||||||
public class Completion : IResourceTool
|
|
||||||
{
|
|
||||||
private readonly ResourceServer Server;
|
|
||||||
private readonly HttpClient _httpClient;
|
|
||||||
private const string Prefix = "completion/";
|
|
||||||
private List<string> Executables = new List<string>();
|
|
||||||
|
|
||||||
public Completion(ResourceServer server, HttpClient httpClient)
|
|
||||||
{
|
|
||||||
Server = server;
|
|
||||||
_httpClient = httpClient;
|
|
||||||
|
|
||||||
new Task(() =>
|
|
||||||
{
|
|
||||||
Executables.AddRange(GetInstalledSoftwareExecutables());
|
|
||||||
Executables.AddRange(GetExecutablesFromPath());
|
|
||||||
Executables.AddRange(GetExecutablesFromNetFx());
|
|
||||||
}).Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CanHandle(string path)
|
|
||||||
{
|
|
||||||
return path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task HandleAsync(HttpListenerContext context, string path)
|
|
||||||
{
|
|
||||||
await Task.Delay(0);
|
|
||||||
|
|
||||||
string word = path.Substring(Prefix.Length);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
CompletionItem[] completionItems = Executables
|
|
||||||
.Where(exec => exec.IndexOf(word, 0, StringComparison.OrdinalIgnoreCase) > -1)
|
|
||||||
.Take(100) // Limit the number of results
|
|
||||||
.Select(exec => new CompletionItem
|
|
||||||
{
|
|
||||||
Label = Path.GetFileName(exec),
|
|
||||||
Kind = "Text",
|
|
||||||
Documentation = $"An executable file: {exec}",
|
|
||||||
InsertText = exec
|
|
||||||
})
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
XElement response = new XElement("suggestions",
|
|
||||||
completionItems.Select(item => new XElement("item",
|
|
||||||
new XElement("label", item.Label),
|
|
||||||
new XElement("kind", item.Kind),
|
|
||||||
new XElement("documentation", item.Documentation),
|
|
||||||
new XElement("insertText", item.InsertText)
|
|
||||||
))
|
|
||||||
);
|
|
||||||
|
|
||||||
Server.ServeResource(context, response.ToString(), "application/xml");
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Server.ServeResource(context, $"<error>Failed to process completion request. {ex.Message}</error>", "application/xml", 500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<string> GetInstalledSoftwareExecutables()
|
|
||||||
{
|
|
||||||
List<string> executables = new List<string>();
|
|
||||||
string registryKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
|
|
||||||
|
|
||||||
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(registryKey))
|
|
||||||
{
|
|
||||||
if (key != null)
|
|
||||||
{
|
|
||||||
foreach (string subKeyName in key.GetSubKeyNames())
|
|
||||||
{
|
|
||||||
using (RegistryKey subKey = key.OpenSubKey(subKeyName))
|
|
||||||
{
|
|
||||||
string installLocation = subKey?.GetValue("InstallLocation") as string;
|
|
||||||
string uninstallString = subKey?.GetValue("UninstallString") as string;
|
|
||||||
|
|
||||||
List<string> executablePaths = FindExecutables(installLocation, uninstallString);
|
|
||||||
executables.AddRange(executablePaths);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return executables;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<string> FindExecutables(string installLocation, string uninstallString)
|
|
||||||
{
|
|
||||||
List<string> executables = new List<string>();
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(installLocation) && Directory.Exists(installLocation))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
List<string> executableFiles = Directory.GetFiles(installLocation, "*.exe", SearchOption.AllDirectories)
|
|
||||||
.OrderByDescending(f => new FileInfo(f).Length)
|
|
||||||
.ToList();
|
|
||||||
executables.AddRange(executableFiles);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Debug.WriteLine($"Error enumerating executables in '{installLocation}': {ex}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(uninstallString))
|
|
||||||
{
|
|
||||||
if (TryParseExecutablePath(uninstallString, out string executablePath))
|
|
||||||
{
|
|
||||||
executables.Add(executablePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return executables;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool TryParseExecutablePath(string s, out string path)
|
|
||||||
{
|
|
||||||
Match match = Regex.Match(s, @"(?<=""|^)([a-zA-Z]:\\[^""]+\.exe)", RegexOptions.IgnoreCase);
|
|
||||||
|
|
||||||
if (match.Success)
|
|
||||||
{
|
|
||||||
path = match.Value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
path = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<string> GetExecutablesFromPath()
|
|
||||||
{
|
|
||||||
List<string> executables = new List<string>();
|
|
||||||
string[] paths = Environment.GetEnvironmentVariable("PATH")?.Split(';');
|
|
||||||
|
|
||||||
if (paths != null)
|
|
||||||
{
|
|
||||||
foreach (string path in paths)
|
|
||||||
{
|
|
||||||
if (Directory.Exists(path))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
executables.AddRange(Directory.GetFiles(path, "*.exe", SearchOption.TopDirectoryOnly));
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Debug.WriteLine($"Error enumerating executables in '{path}': {ex}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return executables;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<string> GetExecutablesFromNetFx()
|
|
||||||
{
|
|
||||||
List<string> executables = new List<string>();
|
|
||||||
|
|
||||||
string windir = Environment.GetEnvironmentVariable("WINDIR");
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(windir))
|
|
||||||
{
|
|
||||||
string[] paths = new string[]
|
|
||||||
{
|
|
||||||
Path.Combine(windir, "Microsoft.NET", "Framework"),
|
|
||||||
Path.Combine(windir, "Microsoft.NET", "Framework64")
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (string path in paths)
|
|
||||||
{
|
|
||||||
if (Directory.Exists(path))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
executables.AddRange(Directory.GetFiles(path, "*.exe", SearchOption.AllDirectories));
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Debug.WriteLine($"Error enumerating executables in '{path}': {ex}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return executables;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CompletionItem
|
|
||||||
{
|
|
||||||
public string Label { get; set; }
|
|
||||||
public string Kind { get; set; }
|
|
||||||
public string Documentation { get; set; }
|
|
||||||
public string InsertText { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace WelsonJS.Launcher.ResourceTools
|
|
||||||
{
|
|
||||||
public class DevTools : IResourceTool
|
|
||||||
{
|
|
||||||
private ResourceServer Server;
|
|
||||||
private readonly HttpClient _httpClient;
|
|
||||||
private const string Prefix = "devtools/";
|
|
||||||
|
|
||||||
public DevTools(ResourceServer server, HttpClient httpClient)
|
|
||||||
{
|
|
||||||
Server = server;
|
|
||||||
_httpClient = httpClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CanHandle(string path)
|
|
||||||
{
|
|
||||||
return path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task HandleAsync(HttpListenerContext context, string path)
|
|
||||||
{
|
|
||||||
string endpoint = path.Substring(Prefix.Length);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string url = Program.GetAppConfig("DevToolsPrefix") + endpoint;
|
|
||||||
string data = await _httpClient.GetStringAsync(url);
|
|
||||||
|
|
||||||
Server.ServeResource(context, data, "application/json");
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Server.ServeResource(context, $"<error>Failed to process DevTools request. {ex.Message}</error>", "application/xml", 500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,343 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace WelsonJS.Launcher.ResourceTools
|
|
||||||
{
|
|
||||||
public class DnsQuery : IResourceTool
|
|
||||||
{
|
|
||||||
private readonly ResourceServer Server;
|
|
||||||
private readonly HttpClient _httpClient;
|
|
||||||
private const string Prefix = "dns-query/";
|
|
||||||
private string DnsServer;
|
|
||||||
private const int DnsPort = 53;
|
|
||||||
private const int Timeout = 5000;
|
|
||||||
private static readonly Random _random = new Random();
|
|
||||||
|
|
||||||
public DnsQuery(ResourceServer server, HttpClient httpClient)
|
|
||||||
{
|
|
||||||
Server = server;
|
|
||||||
_httpClient = httpClient;
|
|
||||||
|
|
||||||
DnsServer = Program.GetAppConfig("DnsServerAddress");
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CanHandle(string path)
|
|
||||||
{
|
|
||||||
return path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task HandleAsync(HttpListenerContext context, string path)
|
|
||||||
{
|
|
||||||
await Task.Delay(0);
|
|
||||||
|
|
||||||
string query = path.Substring(Prefix.Length);
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(query) || query.Length > 255)
|
|
||||||
{
|
|
||||||
Server.ServeResource(context, "<error>Invalid query parameter</error>", "application/xml", 400);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Dictionary<string, List<string>> allRecords = QueryAll(query);
|
|
||||||
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
foreach (var recordType in allRecords.Keys)
|
|
||||||
{
|
|
||||||
result.AppendLine($"\n{recordType} Records:");
|
|
||||||
foreach (var record in allRecords[recordType])
|
|
||||||
{
|
|
||||||
result.AppendLine(record);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string data = result.ToString();
|
|
||||||
Server.ServeResource(context, data, "text/plain", 200);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Server.ServeResource(context, $"<error>Failed to process DNS query. {ex.Message}</error>", "application/xml", 500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<string> QueryA(string domain) => QueryDns(domain, 1);
|
|
||||||
public List<string> QueryNS(string domain) => QueryDns(domain, 2);
|
|
||||||
public List<string> QueryCNAME(string domain) => QueryDns(domain, 5);
|
|
||||||
public List<string> QuerySOA(string domain) => QueryDns(domain, 6);
|
|
||||||
public List<string> QueryPTR(string domain) => QueryDns(domain, 12);
|
|
||||||
public List<string> QueryMX(string domain) => QueryDns(domain, 15);
|
|
||||||
public List<string> QueryTXT(string domain) => QueryDns(domain, 16);
|
|
||||||
public List<string> QueryAAAA(string domain) => QueryDns(domain, 28);
|
|
||||||
public List<string> QuerySRV(string domain) => QueryDns(domain, 33);
|
|
||||||
public List<string> QueryNAPTR(string domain) => QueryDns(domain, 35);
|
|
||||||
public List<string> QueryCAA(string domain) => QueryDns(domain, 257);
|
|
||||||
|
|
||||||
public Dictionary<string, List<string>> QueryAll(string domain)
|
|
||||||
{
|
|
||||||
var results = new Dictionary<string, List<string>>();
|
|
||||||
|
|
||||||
results["A"] = QueryA(domain);
|
|
||||||
results["NS"] = QueryNS(domain);
|
|
||||||
results["CNAME"] = QueryCNAME(domain);
|
|
||||||
results["SOA"] = QuerySOA(domain);
|
|
||||||
results["PTR"] = QueryPTR(domain);
|
|
||||||
results["MX"] = QueryMX(domain);
|
|
||||||
results["TXT"] = QueryTXT(domain);
|
|
||||||
results["AAAA"] = QueryAAAA(domain);
|
|
||||||
results["SRV"] = QuerySRV(domain);
|
|
||||||
results["NAPTR"] = QueryNAPTR(domain);
|
|
||||||
results["CAA"] = QueryCAA(domain);
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<string> QueryDns(string domain, ushort type)
|
|
||||||
{
|
|
||||||
List<string> records = new List<string>();
|
|
||||||
|
|
||||||
// Validate domain format
|
|
||||||
if (string.IsNullOrWhiteSpace(domain))
|
|
||||||
{
|
|
||||||
records.Add("Error: Domain cannot be empty");
|
|
||||||
return records;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Basic domain format validation
|
|
||||||
if (domain.Length > 255 ||
|
|
||||||
!domain.Split('.').All(part => part.Length > 0 && part.Length <= 63))
|
|
||||||
{
|
|
||||||
records.Add("Error: Invalid domain format");
|
|
||||||
return records;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (UdpClient udpClient = new UdpClient(DnsServer, DnsPort))
|
|
||||||
{
|
|
||||||
udpClient.Client.ReceiveTimeout = Timeout;
|
|
||||||
|
|
||||||
byte[] request = CreateDnsQuery(domain, type);
|
|
||||||
udpClient.Send(request, request.Length);
|
|
||||||
|
|
||||||
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, DnsPort);
|
|
||||||
byte[] response = udpClient.Receive(ref remoteEP);
|
|
||||||
|
|
||||||
records.AddRange(ParseDnsResponse(response, type));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
records.Add($"Error: {ex.Message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return records;
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] CreateDnsQuery(string domain, ushort type)
|
|
||||||
{
|
|
||||||
byte[] query = new byte[512];
|
|
||||||
|
|
||||||
query[0] = (byte)_random.Next(0, 256);
|
|
||||||
query[1] = (byte)_random.Next(0, 256);
|
|
||||||
query[2] = 0x01;
|
|
||||||
query[3] = 0x00;
|
|
||||||
query[4] = 0x00;
|
|
||||||
query[5] = 0x01;
|
|
||||||
|
|
||||||
for (int i = 6; i < 12; i++)
|
|
||||||
query[i] = 0x00;
|
|
||||||
|
|
||||||
int position = 12;
|
|
||||||
foreach (string part in domain.Split('.'))
|
|
||||||
{
|
|
||||||
query[position++] = (byte)part.Length;
|
|
||||||
byte[] label = Encoding.ASCII.GetBytes(part);
|
|
||||||
Array.Copy(label, 0, query, position, label.Length);
|
|
||||||
position += label.Length;
|
|
||||||
}
|
|
||||||
query[position++] = 0x00;
|
|
||||||
|
|
||||||
query[position++] = (byte)(type >> 8);
|
|
||||||
query[position++] = (byte)(type & 0xFF);
|
|
||||||
query[position++] = 0x00;
|
|
||||||
query[position++] = 0x01;
|
|
||||||
|
|
||||||
byte[] finalQuery = new byte[position];
|
|
||||||
Array.Copy(query, finalQuery, position);
|
|
||||||
|
|
||||||
return finalQuery;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<string> ParseDnsResponse(byte[] response, ushort queryType)
|
|
||||||
{
|
|
||||||
List<string> results = new List<string>();
|
|
||||||
|
|
||||||
// Check response code from DNS server
|
|
||||||
int responseCode = response[3] & 0x0F;
|
|
||||||
if (responseCode != 0)
|
|
||||||
{
|
|
||||||
string errorMessage = "DNS server returned error: ";
|
|
||||||
switch (responseCode)
|
|
||||||
{
|
|
||||||
case 1: errorMessage += "Format Error"; break;
|
|
||||||
case 2: errorMessage += "Server Failure"; break;
|
|
||||||
case 3: errorMessage += "Name Error (Domain does not exist)"; break;
|
|
||||||
case 4: errorMessage += "Not Implemented"; break;
|
|
||||||
case 5: errorMessage += "Refused"; break;
|
|
||||||
default: errorMessage += $"Unknown Error ({responseCode})"; break;
|
|
||||||
}
|
|
||||||
results.Add(errorMessage);
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
int answerCount = (response[6] << 8) | response[7];
|
|
||||||
if (answerCount == 0)
|
|
||||||
{
|
|
||||||
results.Add("No records found.");
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
int position = 12; // Skip DNS header
|
|
||||||
|
|
||||||
while (response[position] != 0)
|
|
||||||
position += response[position] + 1;
|
|
||||||
position += 5; // End of Question section
|
|
||||||
|
|
||||||
for (int i = 0; i < answerCount; i++)
|
|
||||||
{
|
|
||||||
while (response[position] != 0 && (response[position] & 0xC0) == 0)
|
|
||||||
position += response[position] + 1;
|
|
||||||
position += 2; // Skip Type, Class fields
|
|
||||||
|
|
||||||
ushort recordType = (ushort)((response[position] << 8) | response[position + 1]);
|
|
||||||
position += 8; // Skip TTL and Data length fields
|
|
||||||
|
|
||||||
ushort dataLength = (ushort)((response[position] << 8) | response[position + 1]);
|
|
||||||
position += 2; // Read Data Length
|
|
||||||
|
|
||||||
byte[] data = new byte[dataLength];
|
|
||||||
Array.Copy(response, position, data, 0, dataLength);
|
|
||||||
position += dataLength;
|
|
||||||
|
|
||||||
switch (recordType)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
results.Add($"A: {new IPAddress(data)}");
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
results.Add($"NS: {DecodeDomainName(response, data, 0)}");
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
results.Add($"CNAME: {DecodeDomainName(response, data, 0)}");
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
results.Add($"SOA: {DecodeDomainName(response, data, 0)}");
|
|
||||||
break;
|
|
||||||
case 12:
|
|
||||||
results.Add($"PTR: {DecodeDomainName(response, data, 0)}");
|
|
||||||
break;
|
|
||||||
case 15:
|
|
||||||
// MX record processing (priority and exchange)
|
|
||||||
if (data.Length >= 2)
|
|
||||||
{
|
|
||||||
ushort priority = (ushort)((data[0] << 8) | data[1]);
|
|
||||||
string exchange = DecodeDomainName(response, data, 2); // Decode domain name after 2 bytes
|
|
||||||
results.Add($"MX: Priority {priority}, Exchange {exchange}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
results.Add($"MX: Invalid data length.");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 16:
|
|
||||||
int txtPos = 0;
|
|
||||||
while (txtPos < data.Length)
|
|
||||||
{
|
|
||||||
int txtLength = data[txtPos++];
|
|
||||||
results.Add($"TXT: {Encoding.UTF8.GetString(data, txtPos, txtLength)}");
|
|
||||||
txtPos += txtLength;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 28:
|
|
||||||
results.Add($"AAAA: {new IPAddress(data)}");
|
|
||||||
break;
|
|
||||||
case 33:
|
|
||||||
ushort prioritySrv = (ushort)((data[0] << 8) | data[1]);
|
|
||||||
ushort weight = (ushort)((data[2] << 8) | data[3]);
|
|
||||||
ushort port = (ushort)((data[4] << 8) | data[5]);
|
|
||||||
string target = DecodeDomainName(response, data, 6);
|
|
||||||
results.Add($"SRV: Priority {prioritySrv}, Weight {weight}, Port {port}, Target {target}");
|
|
||||||
break;
|
|
||||||
case 35:
|
|
||||||
if (data.Length >= 7)
|
|
||||||
{
|
|
||||||
ushort order = (ushort)((data[0] << 8) | data[1]);
|
|
||||||
ushort preference = (ushort)((data[2] << 8) | data[3]);
|
|
||||||
// Extract flags, services, regexp and replacement
|
|
||||||
results.Add($"NAPTR: Order {order}, Preference {preference}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
results.Add($"NAPTR: Invalid data length: {BitConverter.ToString(data)}");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 257:
|
|
||||||
if (data.Length >= 2)
|
|
||||||
{
|
|
||||||
byte flags = data[0];
|
|
||||||
int tagLen = data[1];
|
|
||||||
if (data.Length >= 2 + tagLen)
|
|
||||||
{
|
|
||||||
string tag = Encoding.ASCII.GetString(data, 2, tagLen);
|
|
||||||
string value = Encoding.ASCII.GetString(data, 2 + tagLen, data.Length - 2 - tagLen);
|
|
||||||
results.Add($"CAA: Flags {flags}, Tag {tag}, Value {value}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
results.Add($"CAA: Invalid data length: {BitConverter.ToString(data)}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
results.Add($"CAA: Invalid data length: {BitConverter.ToString(data)}");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
results.Add($"Unknown Type {recordType}: {BitConverter.ToString(data)}");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string DecodeDomainName(byte[] response, byte[] data, int startIndex)
|
|
||||||
{
|
|
||||||
int position = startIndex;
|
|
||||||
List<string> labels = new List<string>();
|
|
||||||
|
|
||||||
while (data[position] != 0)
|
|
||||||
{
|
|
||||||
// Handle 0xC0 pointer (compressed domain name handling)
|
|
||||||
if ((data[position] & 0xC0) == 0xC0)
|
|
||||||
{
|
|
||||||
int pointer = ((data[position] & 0x3F) << 8) | data[position + 1];
|
|
||||||
return DecodeDomainName(response, response, pointer); // Recursive call to decode from the pointer
|
|
||||||
}
|
|
||||||
|
|
||||||
int labelLength = data[position++];
|
|
||||||
labels.Add(Encoding.ASCII.GetString(data, position, labelLength));
|
|
||||||
position += labelLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
return string.Join(".", labels);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Configuration;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Resources;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
|
|
||||||
namespace WelsonJS.Launcher.ResourceTools
|
|
||||||
{
|
|
||||||
public class Settings : IResourceTool
|
|
||||||
{
|
|
||||||
private readonly ResourceServer Server;
|
|
||||||
private readonly HttpClient _httpClient;
|
|
||||||
private const string Prefix = "settings";
|
|
||||||
|
|
||||||
public Settings(ResourceServer server, HttpClient httpClient)
|
|
||||||
{
|
|
||||||
Server = server;
|
|
||||||
_httpClient = httpClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CanHandle(string path)
|
|
||||||
{
|
|
||||||
return path.Equals(Prefix, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task HandleAsync(HttpListenerContext context, string path)
|
|
||||||
{
|
|
||||||
await Task.Delay(0);
|
|
||||||
|
|
||||||
// Get current namespace (e.g., WelsonJS.Launcher)
|
|
||||||
string ns = typeof(Program).Namespace;
|
|
||||||
|
|
||||||
// Build resource base name (e.g., WelsonJS.Launcher.Properties.Resources)
|
|
||||||
string resourceBaseName = ns + ".Properties.Resources";
|
|
||||||
|
|
||||||
// Load resource strings using ResourceManager
|
|
||||||
var resourceManager = new ResourceManager(resourceBaseName, Assembly.GetExecutingAssembly());
|
|
||||||
var resourceSet = resourceManager.GetResourceSet(
|
|
||||||
System.Globalization.CultureInfo.CurrentCulture,
|
|
||||||
true,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
var resourceStrings = new Dictionary<string, string>();
|
|
||||||
foreach (System.Collections.DictionaryEntry entry in resourceSet)
|
|
||||||
{
|
|
||||||
if (entry.Value is string strValue)
|
|
||||||
{
|
|
||||||
resourceStrings[(string)entry.Key] = strValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load settings from app.config
|
|
||||||
var appConfig = ConfigurationManager.AppSettings.AllKeys
|
|
||||||
.ToDictionary(k => k, k => ConfigurationManager.AppSettings[k]);
|
|
||||||
|
|
||||||
// Merge by starting with resourceStrings and letting app.config override
|
|
||||||
var finalConfig = new Dictionary<string, string>(resourceStrings);
|
|
||||||
foreach (var kv in appConfig)
|
|
||||||
{
|
|
||||||
finalConfig[kv.Key] = kv.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate XML using XElement
|
|
||||||
XElement xml = new XElement("settings",
|
|
||||||
finalConfig.Select(kv => new XElement(kv.Key, kv.Value))
|
|
||||||
);
|
|
||||||
|
|
||||||
Server.ServeResource(context, xml.ToString(), "application/xml");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,103 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Net;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Net.Http;
|
|
||||||
|
|
||||||
namespace WelsonJS.Launcher.ResourceTools
|
|
||||||
{
|
|
||||||
public class Tfa : IResourceTool
|
|
||||||
{
|
|
||||||
private readonly ResourceServer Server;
|
|
||||||
private readonly HttpClient _httpClient;
|
|
||||||
private const string Prefix = "tfa/";
|
|
||||||
private const string Base32Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
|
||||||
|
|
||||||
public Tfa(ResourceServer server, HttpClient httpClient)
|
|
||||||
{
|
|
||||||
Server = server;
|
|
||||||
_httpClient = httpClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CanHandle(string path)
|
|
||||||
{
|
|
||||||
return path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task HandleAsync(HttpListenerContext context, string path)
|
|
||||||
{
|
|
||||||
await Task.Delay(0);
|
|
||||||
|
|
||||||
string endpoint = path.Substring(Prefix.Length);
|
|
||||||
|
|
||||||
if (endpoint.Equals("pubkey"))
|
|
||||||
{
|
|
||||||
Server.ServeResource(context, GetPubKey(), "text/plain", 200);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Server.ServeResource(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetOtp(string key)
|
|
||||||
{
|
|
||||||
byte[] binaryKey = DecodeBase32(key.Replace(" ", ""));
|
|
||||||
long timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds() / 30;
|
|
||||||
byte[] timestampBytes = BitConverter.GetBytes(timestamp);
|
|
||||||
Array.Reverse(timestampBytes); // Ensure big-endian order
|
|
||||||
|
|
||||||
using (var hmac = new HMACSHA1(binaryKey))
|
|
||||||
{
|
|
||||||
byte[] hash = hmac.ComputeHash(timestampBytes);
|
|
||||||
int offset = hash[hash.Length - 1] & 0xF;
|
|
||||||
|
|
||||||
int otp = ((hash[offset] & 0x7F) << 24) |
|
|
||||||
((hash[offset + 1] & 0xFF) << 16) |
|
|
||||||
((hash[offset + 2] & 0xFF) << 8) |
|
|
||||||
(hash[offset + 3] & 0xFF);
|
|
||||||
|
|
||||||
return otp % 1000000; // Ensure 6-digit OTP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetPubKey()
|
|
||||||
{
|
|
||||||
using (var rng = RandomNumberGenerator.Create())
|
|
||||||
{
|
|
||||||
var key = new char[16];
|
|
||||||
var randomBytes = new byte[16];
|
|
||||||
rng.GetBytes(randomBytes);
|
|
||||||
|
|
||||||
for (int i = 0; i < 16; i++)
|
|
||||||
{
|
|
||||||
key[i] = Base32Chars[randomBytes[i] % Base32Chars.Length];
|
|
||||||
}
|
|
||||||
|
|
||||||
return string.Join(" ", Enumerable.Range(0, 4).Select(i => new string(key, i * 4, 4)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] DecodeBase32(string key)
|
|
||||||
{
|
|
||||||
int buffer = 0, bitsLeft = 0;
|
|
||||||
var binaryKey = new List<byte>();
|
|
||||||
|
|
||||||
foreach (char c in key)
|
|
||||||
{
|
|
||||||
int value = Base32Chars.IndexOf(c);
|
|
||||||
if (value < 0) continue; // Ignore invalid characters
|
|
||||||
|
|
||||||
buffer = (buffer << 5) + value;
|
|
||||||
bitsLeft += 5;
|
|
||||||
if (bitsLeft >= 8)
|
|
||||||
{
|
|
||||||
bitsLeft -= 8;
|
|
||||||
binaryKey.Add((byte)((buffer >> bitsLeft) & 0xFF));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return binaryKey.ToArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
using System.Net;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace WelsonJS.Launcher.ResourceTools
|
|
||||||
{
|
|
||||||
public class Whois : IResourceTool
|
|
||||||
{
|
|
||||||
private readonly ResourceServer Server;
|
|
||||||
private readonly HttpClient _httpClient;
|
|
||||||
private const string Prefix = "whois/";
|
|
||||||
|
|
||||||
public Whois(ResourceServer server, HttpClient httpClient)
|
|
||||||
{
|
|
||||||
Server = server;
|
|
||||||
_httpClient = httpClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CanHandle(string path)
|
|
||||||
{
|
|
||||||
return path.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task HandleAsync(HttpListenerContext context, string path)
|
|
||||||
{
|
|
||||||
string query = path.Substring(Prefix.Length);
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(query) || query.Length > 255)
|
|
||||||
{
|
|
||||||
Server.ServeResource(context, "<error>Invalid query parameter</error>", "application/xml", 400);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
string clientAddress = Program.GetAppConfig("WhoisClientAddress");
|
|
||||||
|
|
||||||
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, Program.GetAppConfig("WhoisServerUrl"))
|
|
||||||
{
|
|
||||||
Content = new StringContent($"query={Uri.EscapeDataString(query)}&ip={clientAddress}", Encoding.UTF8, "application/x-www-form-urlencoded")
|
|
||||||
};
|
|
||||||
|
|
||||||
request.Headers.Add("Accept", "*/*");
|
|
||||||
request.Headers.Add("User-Agent", context.Request.UserAgent);
|
|
||||||
_httpClient.DefaultRequestHeaders.Referrer = new Uri(Program.GetAppConfig("WhoisReferrerUrl"));
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
HttpResponseMessage response = await _httpClient.SendAsync(request);
|
|
||||||
string responseBody = await response.Content.ReadAsStringAsync();
|
|
||||||
|
|
||||||
Server.ServeResource(context, responseBody, "text/plain", (int)response.StatusCode);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Server.ServeResource(context, $"<error>Failed to process WHOIS request. {ex.Message}</error>", "application/xml", 500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 317 B |
Before Width: | Height: | Size: 974 B |
Before Width: | Height: | Size: 179 B |
Before Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 230 B |
Before Width: | Height: | Size: 837 B |
Before Width: | Height: | Size: 796 B |
|
@ -56,38 +56,20 @@
|
||||||
<ApplicationIcon>favicon.ico</ApplicationIcon>
|
<ApplicationIcon>favicon.ico</ApplicationIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Microsoft.CSharp" />
|
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Configuration" />
|
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
<Reference Include="System.Deployment" />
|
<Reference Include="System.Deployment" />
|
||||||
<Reference Include="System.Drawing" />
|
<Reference Include="System.Drawing" />
|
||||||
<Reference Include="System.Net.Http" />
|
<Reference Include="System.IO.Compression.FileSystem" />
|
||||||
|
<Reference Include="System.IO.Compression.ZipFile, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
<Reference Include="System.Windows.Forms" />
|
<Reference Include="System.Windows.Forms" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
<Reference Include="System.Xml.Linq" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="IResourceTool.cs" />
|
|
||||||
<Compile Include="ResourceTools\CitiQuery.cs" />
|
|
||||||
<Compile Include="ResourceTools\Settings.cs" />
|
|
||||||
<Compile Include="ResourceTools\Completion.cs" />
|
|
||||||
<Compile Include="ResourceTools\DevTools.cs" />
|
|
||||||
<Compile Include="ResourceTools\DnsQuery.cs" />
|
|
||||||
<Compile Include="ResourceTools\Tfa.cs" />
|
|
||||||
<Compile Include="ResourceTools\Whois.cs" />
|
|
||||||
<Compile Include="EnvForm.cs">
|
|
||||||
<SubType>Form</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="EnvForm.Designer.cs">
|
|
||||||
<DependentUpon>EnvForm.cs</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="InstancesForm.cs">
|
|
||||||
<SubType>Form</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="InstancesForm.Designer.cs">
|
|
||||||
<DependentUpon>InstancesForm.cs</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="MainForm.cs">
|
<Compile Include="MainForm.cs">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
@ -96,41 +78,25 @@
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="GlobalSettingsForm.cs">
|
|
||||||
<SubType>Form</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="GlobalSettingsForm.Designer.cs">
|
|
||||||
<DependentUpon>GlobalSettingsForm.cs</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="ResourceServer.cs" />
|
|
||||||
<Compile Include="ZipExtractor.cs" />
|
|
||||||
<EmbeddedResource Include="EnvForm.resx">
|
|
||||||
<DependentUpon>EnvForm.cs</DependentUpon>
|
|
||||||
</EmbeddedResource>
|
|
||||||
<EmbeddedResource Include="InstancesForm.resx">
|
|
||||||
<DependentUpon>InstancesForm.cs</DependentUpon>
|
|
||||||
</EmbeddedResource>
|
|
||||||
<EmbeddedResource Include="MainForm.resx">
|
<EmbeddedResource Include="MainForm.resx">
|
||||||
<DependentUpon>MainForm.cs</DependentUpon>
|
<DependentUpon>MainForm.cs</DependentUpon>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Include="Properties\Resources.resx">
|
<EmbeddedResource Include="Properties\Resources.resx">
|
||||||
<Generator>ResXFileCodeGenerator</Generator>
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
<SubType>Designer</SubType>
|
|
||||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
<EmbeddedResource Include="GlobalSettingsForm.resx">
|
<Compile Include="Properties\Resources.Designer.cs">
|
||||||
<DependentUpon>GlobalSettingsForm.cs</DependentUpon>
|
<AutoGen>True</AutoGen>
|
||||||
</EmbeddedResource>
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
</Compile>
|
||||||
<None Include="app.config" />
|
<None Include="app.config" />
|
||||||
|
<None Include="packages.config" />
|
||||||
<None Include="Properties\Settings.settings">
|
<None Include="Properties\Settings.settings">
|
||||||
<Generator>SettingsSingleFileGenerator</Generator>
|
<Generator>SettingsSingleFileGenerator</Generator>
|
||||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||||
</None>
|
</None>
|
||||||
<Compile Include="Properties\Resources.Designer.cs">
|
|
||||||
<AutoGen>True</AutoGen>
|
|
||||||
<DesignTime>True</DesignTime>
|
|
||||||
<DependentUpon>Resources.resx</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="Properties\Settings.Designer.cs">
|
<Compile Include="Properties\Settings.Designer.cs">
|
||||||
<AutoGen>True</AutoGen>
|
<AutoGen>True</AutoGen>
|
||||||
<DependentUpon>Settings.settings</DependentUpon>
|
<DependentUpon>Settings.settings</DependentUpon>
|
||||||
|
@ -144,22 +110,7 @@
|
||||||
<None Include="Resources\icon_zip_128.png" />
|
<None Include="Resources\icon_zip_128.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="favicon.ico" />
|
<Content Include="favicon.ico" />
|
||||||
<None Include="Resources\favicon.ico" />
|
|
||||||
<None Include="Resources\icon_check_32.png" />
|
|
||||||
<None Include="Resources\icon_directory_32.png" />
|
|
||||||
<None Include="Resources\icon_file_32.png" />
|
|
||||||
<None Include="Resources\icon_export_32.png" />
|
|
||||||
<None Include="Resources\icon_import_32.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="Resources\icon_delete_32.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="Resources\icon_start_32.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedResource Include="editor.html" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
|
@ -1,275 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
|
|
||||||
namespace WelsonJS.Launcher
|
|
||||||
{
|
|
||||||
public class ZipExtractor
|
|
||||||
{
|
|
||||||
class Extractor
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string FileName { get; set; }
|
|
||||||
public string Path { get; set; }
|
|
||||||
public Func<string, string, string> ExtractCommand { get; set; }
|
|
||||||
public bool UseCmd { get; set; } = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly List<Extractor> AvailableExtractors;
|
|
||||||
|
|
||||||
public ZipExtractor()
|
|
||||||
{
|
|
||||||
// Searches the computer for any known third-party ZIP utilities.
|
|
||||||
AvailableExtractors = new List<Extractor>{
|
|
||||||
new Extractor
|
|
||||||
{
|
|
||||||
Name = "7z",
|
|
||||||
FileName = "7z.exe",
|
|
||||||
ExtractCommand = (src, dest) => $"x \"{src}\" -o\"{dest}\" -y"
|
|
||||||
},
|
|
||||||
new Extractor
|
|
||||||
{
|
|
||||||
Name = "WinRAR",
|
|
||||||
FileName = "rar.exe",
|
|
||||||
ExtractCommand = (src, dest) => $"x -o+ \"{src}\" \"{dest}\\\""
|
|
||||||
},
|
|
||||||
new Extractor
|
|
||||||
{
|
|
||||||
Name = "PeaZip",
|
|
||||||
FileName = "peazip.exe",
|
|
||||||
ExtractCommand = (src, dest) => $"-ext2simple \"{src}\" \"{dest}\""
|
|
||||||
},
|
|
||||||
new Extractor
|
|
||||||
{
|
|
||||||
Name = "WinZip",
|
|
||||||
FileName = "wzunzip.exe",
|
|
||||||
ExtractCommand = (src, dest) => $"-d \"{dest}\" \"{src}\""
|
|
||||||
},
|
|
||||||
new Extractor
|
|
||||||
{
|
|
||||||
Name = "ALZip",
|
|
||||||
FileName = "ALZipcon.exe",
|
|
||||||
ExtractCommand = (src, dest) => $"-x \"{src}\" \"{dest}\""
|
|
||||||
},
|
|
||||||
new Extractor
|
|
||||||
{
|
|
||||||
Name = "Bandizip",
|
|
||||||
FileName = "Bandizip.exe",
|
|
||||||
ExtractCommand = (src, dest) => $"x -o:\"{dest}\" \"{src}\" -y"
|
|
||||||
},
|
|
||||||
new Extractor
|
|
||||||
{
|
|
||||||
Name = "IZArc",
|
|
||||||
FileName = "izarce.exe",
|
|
||||||
ExtractCommand = (src, dest) => $"-d -p\"{dest}\" \"{src}\""
|
|
||||||
},
|
|
||||||
new Extractor
|
|
||||||
{
|
|
||||||
Name = "jar (Java SDK)",
|
|
||||||
FileName = "jar.exe",
|
|
||||||
ExtractCommand = (src, dest) => $"xf \"{src}\"",
|
|
||||||
UseCmd = true
|
|
||||||
},
|
|
||||||
new Extractor
|
|
||||||
{
|
|
||||||
Name = "tar (Windows)", // Windows 10 build 17063 or later
|
|
||||||
FileName = "tar.exe",
|
|
||||||
ExtractCommand = (src, dest) => $"-xf \"{src}\" -C \"{dest}\""
|
|
||||||
},
|
|
||||||
new Extractor
|
|
||||||
{
|
|
||||||
Name = "unzip", // Info-ZIP, Cygwin
|
|
||||||
FileName = "unzip.exe",
|
|
||||||
ExtractCommand = (src, dest) => $"\"{src}\" -d \"{dest}\" -o"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Task.Run(() => CheckAvailableExtractors());
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Extract(string filePath, string workingDirectory)
|
|
||||||
{
|
|
||||||
if (!File.Exists(filePath))
|
|
||||||
throw new FileNotFoundException("The specified file does not exist.", filePath);
|
|
||||||
|
|
||||||
if (!filePath.EndsWith(".zip", StringComparison.OrdinalIgnoreCase))
|
|
||||||
throw new ArgumentException("The specified file is not a ZIP archive.");
|
|
||||||
|
|
||||||
if (!IsValidFile(filePath))
|
|
||||||
throw new InvalidDataException("The specified file is not a valid ZIP archive.");
|
|
||||||
|
|
||||||
Directory.CreateDirectory(workingDirectory);
|
|
||||||
|
|
||||||
foreach (var extractor in AvailableExtractors.Where(e => e.Path != null))
|
|
||||||
{
|
|
||||||
if (RunProcess(extractor, filePath, workingDirectory, true))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ExtractUsingPowerShell(filePath, workingDirectory, true))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (ExtractUsingShell(filePath, workingDirectory, true))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsValidFile(string filePath)
|
|
||||||
{
|
|
||||||
byte[] signature = new byte[4];
|
|
||||||
|
|
||||||
using (var fs = File.OpenRead(filePath))
|
|
||||||
{
|
|
||||||
if (fs.Length < 4)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
int bytesRead = fs.Read(signature, 0, 4);
|
|
||||||
if (bytesRead < 4)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return signature.SequenceEqual(new byte[] { 0x50, 0x4B, 0x03, 0x04 });
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CheckAvailableExtractors()
|
|
||||||
{
|
|
||||||
var fileNames = AvailableExtractors.Select(e => e.FileName).ToList();
|
|
||||||
|
|
||||||
// Check PATH environment variable
|
|
||||||
var paths = (Environment.GetEnvironmentVariable("PATH") ?? "").Split(Path.PathSeparator);
|
|
||||||
foreach (var dir in paths)
|
|
||||||
{
|
|
||||||
foreach (var fileName in fileNames)
|
|
||||||
{
|
|
||||||
var path = Path.Combine(dir.Trim(), fileName);
|
|
||||||
if (File.Exists(path))
|
|
||||||
{
|
|
||||||
var index = fileNames.IndexOf(fileName);
|
|
||||||
var extractor = AvailableExtractors[index];
|
|
||||||
extractor.Path = path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check common install locations
|
|
||||||
var programDirs = new[]
|
|
||||||
{
|
|
||||||
Path.Combine(Program.GetAppDataPath(), "bin"), // find an extractor from APPDATA directory
|
|
||||||
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles),
|
|
||||||
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86)
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (var rootDir in programDirs)
|
|
||||||
{
|
|
||||||
if (!Directory.Exists(rootDir))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
foreach (var file in Directory.EnumerateFiles(rootDir, "*", SearchOption.AllDirectories))
|
|
||||||
{
|
|
||||||
var fileName = Path.GetFileName(file);
|
|
||||||
if (fileNames.Contains(fileName))
|
|
||||||
{
|
|
||||||
var index = fileNames.IndexOf(fileName);
|
|
||||||
var extractor = AvailableExtractors[index];
|
|
||||||
extractor.Path = file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Trace.TraceInformation($"Ignored file or directory: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool RunProcess(string execFilePath, string arguments, string workingDirectory, bool useCmd = false, bool showConsole = false)
|
|
||||||
{
|
|
||||||
int exitCode = -1;
|
|
||||||
|
|
||||||
string fileName = useCmd ? "cmd.exe" : execFilePath;
|
|
||||||
string adjustedArguments = useCmd ? $"/c \"{execFilePath}\" {arguments}" : arguments;
|
|
||||||
|
|
||||||
var psi = new ProcessStartInfo
|
|
||||||
{
|
|
||||||
FileName = fileName,
|
|
||||||
Arguments = adjustedArguments,
|
|
||||||
WorkingDirectory = workingDirectory,
|
|
||||||
RedirectStandardOutput = !showConsole,
|
|
||||||
RedirectStandardError = !showConsole,
|
|
||||||
UseShellExecute = showConsole,
|
|
||||||
CreateNoWindow = !showConsole
|
|
||||||
};
|
|
||||||
|
|
||||||
using (var process = new Process { StartInfo = psi, EnableRaisingEvents = true })
|
|
||||||
{
|
|
||||||
process.Start();
|
|
||||||
process.WaitForExit();
|
|
||||||
exitCode = process.ExitCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exitCode != 0)
|
|
||||||
Trace.TraceWarning($"{fileName} exit with code {exitCode}");
|
|
||||||
else
|
|
||||||
Trace.TraceInformation($"{fileName} finished successfully");
|
|
||||||
|
|
||||||
return exitCode == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool RunProcess(Extractor extractor, string filePath, string workingDirectory, bool showConsole = false)
|
|
||||||
{
|
|
||||||
return RunProcess(extractor.Path,
|
|
||||||
extractor.ExtractCommand(filePath, workingDirectory),
|
|
||||||
workingDirectory,
|
|
||||||
extractor.UseCmd,
|
|
||||||
showConsole
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ExtractUsingPowerShell(string filePath, string workingDirectory, bool showConsole = false)
|
|
||||||
{
|
|
||||||
var escapedSrc = filePath.Replace("'", "''");
|
|
||||||
var escapedDest = workingDirectory.Replace("'", "''");
|
|
||||||
var script = $"Expand-Archive -LiteralPath '{escapedSrc}' -DestinationPath '{escapedDest}' -Force";
|
|
||||||
|
|
||||||
return RunProcess("powershell.exe", $"-NoProfile -Command \"{script}\"", workingDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ExtractUsingShell(string filePath, string workingDirectory, bool showConsole = false)
|
|
||||||
{
|
|
||||||
var shellAppType = Type.GetTypeFromProgID("Shell.Application");
|
|
||||||
if (shellAppType == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
dynamic shell = Activator.CreateInstance(shellAppType);
|
|
||||||
if (shell == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
dynamic zip = shell.NameSpace(filePath);
|
|
||||||
dynamic dest = shell.NameSpace(workingDirectory);
|
|
||||||
if (zip == null || dest == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
int expected = zip.Items().Count;
|
|
||||||
dest.CopyHere(zip.Items(), 16);
|
|
||||||
|
|
||||||
// wait (max 30 s) until all files appear
|
|
||||||
var sw = Stopwatch.StartNew();
|
|
||||||
while (dest.Items().Count < expected && sw.Elapsed < TimeSpan.FromSeconds(30))
|
|
||||||
System.Threading.Thread.Sleep(200);
|
|
||||||
|
|
||||||
Marshal.ReleaseComObject(zip);
|
|
||||||
Marshal.ReleaseComObject(dest);
|
|
||||||
Marshal.ReleaseComObject(shell);
|
|
||||||
|
|
||||||
return dest.Items().Count == expected;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +1,3 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<appSettings>
|
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/></startup></configuration>
|
||||||
<add key="ResourceServerPrefix" value="http://localhost:3000/"/>
|
|
||||||
<add key="RepositoryUrl" value="https://github.com/gnh1201/welsonjs"/>
|
|
||||||
<add key="CopilotUrl" value="https://copilot.microsoft.com/"/>
|
|
||||||
<add key="DevToolsPrefix" value="http://localhost:9222/"/>
|
|
||||||
<add key="AzureAiServicePrefix" value="https://ai-catswords656881030318.services.ai.azure.com/"/>
|
|
||||||
<add key="AzureAiServiceApiKey" value=""/>
|
|
||||||
<add key="AzureAiServiceApiVersion" value="2024-05-01-preview"/>
|
|
||||||
<add key="WhoisServerUrl" value="https://xn--c79as89aj0e29b77z.xn--3e0b707e/kor/whois.jsc"/>
|
|
||||||
<add key="WhoisReferrerUrl" value="https://xn--c79as89aj0e29b77z.xn--3e0b707e/kor/whois/whois.jsp"/>
|
|
||||||
<add key="WhoisClientAddress" value="141.101.82.1"/>
|
|
||||||
<add key="DnsServerAddress" value="1.1.1.1"/>
|
|
||||||
<add key="BlobStoragePrefix" value="https://catswords.blob.core.windows.net/welsonjs/"/>
|
|
||||||
<add key="BlobConfigUrl" value="https://catswords.blob.core.windows.net/welsonjs/blob.config.xml"/>
|
|
||||||
<add key="HttpClientTimeout" value="90"/>
|
|
||||||
<add key="CitiApiKey" value=""/>
|
|
||||||
<add key="CitiApiPrefix" value="https://api.criminalip.io/v1/"/>
|
|
||||||
</appSettings>
|
|
||||||
<startup>
|
|
||||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
|
|
||||||
</startup>
|
|
||||||
</configuration>
|
|
||||||
|
|
|
@ -1,670 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>WelsonJS Editor</title>
|
|
||||||
<meta name="title" content="WelsonJS Editor">
|
|
||||||
<meta name="description" content="WelsonJS can build a Windows app on the Windows built-in JavaScript engine.">
|
|
||||||
<meta name="keywords" content="ecmascript, javascript, windows">
|
|
||||||
<meta name="robots" content="noindex, nofollow">
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
||||||
<meta name="language" content="English">
|
|
||||||
<meta name="author" content="Namhyeon Go (abuse@catswords.net)">
|
|
||||||
<style>
|
|
||||||
html, body, #app, #app > .app {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
#container {
|
|
||||||
border: 1px solid grey;
|
|
||||||
height: calc(100% - 167px);
|
|
||||||
display: flex;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
#editor {
|
|
||||||
flex: 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
#promptEditor {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.banner {
|
|
||||||
text-align: center;
|
|
||||||
padding: 10px;
|
|
||||||
background-color: #f1f1f1;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
<script>
|
|
||||||
var require = {
|
|
||||||
paths: {
|
|
||||||
vs: 'http://localhost:3000/ajax/libs/monaco-editor/0.52.2/min/vs'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<script src="http://localhost:3000/ajax/libs/lodash/4.17.21/lodash.min.js" integrity="sha384-H6KKS1H1WwuERMSm+54dYLzjg0fKqRK5ZRyASdbrI/lwrCc6bXEmtGYr5SwvP1pZ" crossorigin="anonymous"></script>
|
|
||||||
<script src="http://localhost:3000/ajax/libs/jsoneditor/10.1.3/jsoneditor.min.js" integrity="sha384-NdVVc20Tze856ZAWEoJNCk0mL4zJrGztRwULc5Hz25HUXQQgYtmjFtgVAxR4p5dD" crossorigin="anonymous"></script>
|
|
||||||
<script src="http://localhost:3000/ajax/libs/react/18.3.1/umd/react.production.min.js" integrity="sha384-DGyLxAyjq0f9SPpVevD6IgztCFlnMF6oW/XQGmfe+IsZ8TqEiDrcHkMLKI6fiB/Z" crossorigin="anonymous"></script>
|
|
||||||
<script src="http://localhost:3000/ajax/libs/react-dom/18.3.1/umd/react-dom.production.min.js" integrity="sha384-gTGxhz21lVGYNMcdJOyq01Edg0jhn/c22nsx0kyqP0TxaV5WVdsSH1fSDUf5YJj1" crossorigin="anonymous"></script>
|
|
||||||
<script src="http://localhost:3000/ajax/libs/axios/1.8.4/axios.min.js" integrity="sha384-06w+raHvkSL3+E7mbQ2X6DZwI5A3veU8Ba+NLrAPxxRGw4Xy78sihHDHQMustMM4" crossorigin="anonymous"></script>
|
|
||||||
<script src="http://localhost:3000/ajax/libs/fast-xml-parser/4.5.1/fxparser.min.js" integrity="sha384-ae/HepOQ8hiJ/VA6yGwPMGXQXOkT/lJpjlcQ7EUgibUcfnBltuozgNj4IgOZ9QLc" crossorigin="anonymous"></script>
|
|
||||||
<script src="http://localhost:3000/ajax/libs/dompurify/3.2.4/purify.min.js" integrity="sha384-eEu5CTj3qGvu9PdJuS+YlkNi7d2XxQROAFYOr59zgObtlcux1ae1Il3u7jvdCSWu" crossorigin="anonymous"></script>
|
|
||||||
<script src="http://localhost:3000/ajax/libs/monaco-editor/0.52.2/min/vs/loader.js" integrity="sha384-pHG02SG8pId94Np3AbPmBEJ1yPqaH0IkJGLSNGXYmuGhkazT8Lr/57WYpbkGjJtu" crossorigin="anonymous"></script>
|
|
||||||
<script src="http://localhost:3000/ajax/libs/monaco-editor/0.52.2/min/vs/editor/editor.main.js" integrity="sha384-fj9z+NUc93I3woCCy5IRQfrQ8Amu1E27tllwgb5gz3d9Vr1ymS13xcF6two3e4KH" crossorigin="anonymous"></script>
|
|
||||||
<script>
|
|
||||||
function loadResource(url, mimeType, integrity) {
|
|
||||||
mimeType = mimeType || 'application/javascript';
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
let el;
|
|
||||||
|
|
||||||
if (mimeType === 'text/css') {
|
|
||||||
el = document.createElement('link');
|
|
||||||
el.rel = 'stylesheet';
|
|
||||||
el.type = mimeType;
|
|
||||||
el.href = url;
|
|
||||||
} else {
|
|
||||||
el = document.createElement('script');
|
|
||||||
el.type = mimeType;
|
|
||||||
el.src = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (integrity) {
|
|
||||||
el.integrity = integrity;
|
|
||||||
el.crossOrigin = 'anonymous';
|
|
||||||
}
|
|
||||||
|
|
||||||
el.onload = resolve;
|
|
||||||
el.onerror = reject;
|
|
||||||
|
|
||||||
(mimeType === 'text/css' ? document.head : document.body).appendChild(el);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Promise.all([
|
|
||||||
loadResource("http://localhost:3000/ajax/libs/metroui/dev/lib/metro.css", "text/css", "sha384-4XgOiXH2ZMaWt5s5B35yKi7EAOabhZvx7wO8Jr71q2vZ+uONdRza/6CsK2kpyocd"),
|
|
||||||
loadResource("http://localhost:3000/ajax/libs/metroui/dev/lib/icons.css", "text/css", "sha384-FuLND994etg+RtnpPSPMyNBvL+fEz+xGhbN61WUWuDEeZ+wJzcQ8SGqAMuI5hWrt"),
|
|
||||||
loadResource("http://localhost:3000/ajax/libs/monaco-editor/0.52.2/min/vs/editor/editor.main.css", "text/css", "sha384-06yHXpYRlHEPaR4AS0fB/W+lMN09Zh5e1XMtfkNQdHV38OlhfkOEW5M+pCj3QskC"),
|
|
||||||
loadResource("http://localhost:3000/ajax/libs/jsoneditor/10.1.3/jsoneditor.min.css", "text/css", "sha384-cj1rYBc4/dVYAknZMTkVCDRL6Knzugf32igVqsuFW0iRWFHKH8Ci8+ekC8gNsFZ+")
|
|
||||||
]).then(() => {
|
|
||||||
const _e = React.createElement;
|
|
||||||
|
|
||||||
function Button({ id, icon, caption, onClick }) {
|
|
||||||
return _e(
|
|
||||||
'button',
|
|
||||||
{ id, className: 'ribbon-button', onClick },
|
|
||||||
_e('span', { className: `icon ${icon}` }),
|
|
||||||
_e('span', { className: 'caption' }, caption)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function Group({ title, buttons }) {
|
|
||||||
return _e(
|
|
||||||
'div',
|
|
||||||
{ className: 'group' },
|
|
||||||
buttons.map((btn, index) =>
|
|
||||||
_e(Button, { key: index, ...btn })
|
|
||||||
),
|
|
||||||
_e('span', { className: 'title' }, title)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function RibbonMenu({
|
|
||||||
onOpenFileClick, onSaveFileClick, onCopliotClick, onAzureAiClick,
|
|
||||||
onSavePromptClick, onLoadPromptClick, onQueryWhoisClick, onQueryDnsClick,
|
|
||||||
onQueryCitiClick
|
|
||||||
}) {
|
|
||||||
const fileButtons = [
|
|
||||||
{
|
|
||||||
id: 'btnOpenFile',
|
|
||||||
icon: 'mif-folder-open',
|
|
||||||
caption: 'Open File',
|
|
||||||
onClick: onOpenFileClick
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'btnSaveFile',
|
|
||||||
icon: 'mif-floppy-disks',
|
|
||||||
caption: 'Save File',
|
|
||||||
onClick: onSaveFileClick
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
const aiButtons = [
|
|
||||||
{ id: 'btnCopilot', icon: 'mif-rocket', caption: 'Copilot', onClick: onCopliotClick },
|
|
||||||
{ id: 'btnAzureAi', icon: 'mif-rocket', caption: 'Azure AI', onClick: onAzureAiClick },
|
|
||||||
{ id: 'btnSavePrompt', icon: 'mif-floppy-disks', caption: 'Save', onClick: onSavePromptClick },
|
|
||||||
{ id: 'btnLoadPrompt', icon: 'mif-file-upload', caption: 'Load', onClick: onLoadPromptClick }
|
|
||||||
];
|
|
||||||
|
|
||||||
const networkToolsButtons = [
|
|
||||||
{ id: 'btnWhois', icon: 'mif-earth', caption: 'Whois', onClick: onQueryWhoisClick },
|
|
||||||
{ id: 'btnQueryDns', icon: 'mif-earth', caption: 'DNS', onClick: onQueryDnsClick },
|
|
||||||
{ id: 'btnQueryCiti', icon: 'mif-user-secret', caption: 'IP', onClick: onQueryCitiClick }
|
|
||||||
];
|
|
||||||
|
|
||||||
return _e(
|
|
||||||
'nav',
|
|
||||||
{ 'className': 'ribbon-menu' },
|
|
||||||
_e('ul', { className: 'tabs-holder' },
|
|
||||||
_e('li', { className: 'static' }, _e('a', { href: '#heading-tab' }, 'WelsonJS')),
|
|
||||||
_e('li', { className: 'active' }, _e('a', { href: '#editor-tab' }, 'Editor'))
|
|
||||||
),
|
|
||||||
_e('div', { className: 'content-holder' },
|
|
||||||
_e('div', { className: 'section active', id: 'editor-tab' },
|
|
||||||
_e(Group, { title: 'File', buttons: fileButtons }),
|
|
||||||
_e(Group, { title: 'Generative AI', buttons: aiButtons }),
|
|
||||||
_e(Group, { title: 'Network tools', buttons: networkToolsButtons })
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function Editor({ editorRef }) {
|
|
||||||
const containerRef = React.useRef(null);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (!containerRef.current)
|
|
||||||
return;
|
|
||||||
|
|
||||||
require(['vs/editor/editor.main'], () => {
|
|
||||||
const instance = monaco.editor.create(containerRef.current, {
|
|
||||||
value: ['// lib/sayhello.js', 'function say() {', ' console.log("hello");', '}', '', 'exports.say = say;', '', 'exports.VERSIONINFO = "SayHello (sayhello.js) version 0.1";', 'exports.AUTHOR = "abuse@catswords.net";', 'exports.global = global;', 'exports.require = global.require;'].join('\n'),
|
|
||||||
language: 'javascript'
|
|
||||||
});
|
|
||||||
|
|
||||||
editorRef.current = instance;
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return _e('div', { id: 'editor', ref: containerRef });
|
|
||||||
}
|
|
||||||
|
|
||||||
function PromptEditor({ promptEditorRef, promptMessagesRef }) {
|
|
||||||
const containerRef = React.useRef(null);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (!containerRef.current)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const invoke = () => {
|
|
||||||
try {
|
|
||||||
if (promptEditorRef.current) {
|
|
||||||
const updated = promptEditorRef.current.get();
|
|
||||||
promptMessagesRef.current = updated;
|
|
||||||
} else {
|
|
||||||
throw new Error("promptEditorRef.current is null");
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Invalid JSON structure", e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const throttledInvoke = _.throttle(invoke, 300, {
|
|
||||||
leading: true,
|
|
||||||
trailing: true
|
|
||||||
});
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
onChange: throttledInvoke
|
|
||||||
};
|
|
||||||
|
|
||||||
const instance = new JSONEditor(containerRef.current, options);
|
|
||||||
instance.set(promptMessagesRef.current);
|
|
||||||
|
|
||||||
promptEditorRef.current = instance;
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
if (instance) {
|
|
||||||
throttledInvoke.flush();
|
|
||||||
throttledInvoke.cancel();
|
|
||||||
instance.destroy();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return _e('div', { id: 'promptEditor', ref: containerRef });
|
|
||||||
}
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
const serverPrefix = "http://localhost:3000/";
|
|
||||||
const editorRef = React.useRef(null);
|
|
||||||
const promptEditorRef = React.useRef(null);
|
|
||||||
const settingsRef = React.useRef({});
|
|
||||||
const fileNameRef = React.useRef('sayhello.js');
|
|
||||||
const promptMessagesRef = React.useRef([]);
|
|
||||||
|
|
||||||
const fetchSettings = () => axios.get(`${serverPrefix}settings`)
|
|
||||||
.then(response => {
|
|
||||||
const parser = new XMLParser();
|
|
||||||
const result = parser.parse(response.data);
|
|
||||||
settingsRef.current = result.settings;
|
|
||||||
});
|
|
||||||
|
|
||||||
const resizeEditor = () => {
|
|
||||||
if (editorRef.current) {
|
|
||||||
const ribbon = document.querySelector('nav')?.offsetHeight || 0;
|
|
||||||
const banner = document.querySelector('.banner')?.offsetHeight || 0;
|
|
||||||
const h = document.documentElement.clientHeight - ribbon - banner;
|
|
||||||
const editorDiv = document.getElementById('editor');
|
|
||||||
if (editorDiv) editorDiv.style.height = h + 'px';
|
|
||||||
if (editorRef.current) editorRef.current.layout();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getSuggestions = (word) => axios.get(`${serverPrefix}completion/${encodeURIComponent(word)}`)
|
|
||||||
.then(response => {
|
|
||||||
const parser = new XMLParser();
|
|
||||||
const result = parser.parse(response.data);
|
|
||||||
|
|
||||||
if (!result.suggestions || !result.suggestions.item) {
|
|
||||||
return {
|
|
||||||
suggestions: []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const items = Array.isArray(result.suggestions.item) ? result.suggestions.item : [result.suggestions.item];
|
|
||||||
const suggestions = items.map(function (item) {
|
|
||||||
return {
|
|
||||||
label: item.label,
|
|
||||||
kind: monaco.languages.CompletionItemKind.Text,
|
|
||||||
documentation: item.documentation || "",
|
|
||||||
insertText: '"' + item.insertText + '"',
|
|
||||||
range: range
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
suggestions: suggestions
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.catch(function () {
|
|
||||||
return {
|
|
||||||
suggestions: []
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const pushPromptMessage = (role, content) => {
|
|
||||||
promptMessagesRef.current.push({
|
|
||||||
role: role,
|
|
||||||
content: content
|
|
||||||
});
|
|
||||||
promptEditorRef.current.set(promptMessagesRef.current);
|
|
||||||
};
|
|
||||||
|
|
||||||
const navigate = (href) => {
|
|
||||||
const a = document.createElement("a");
|
|
||||||
a.href = href;
|
|
||||||
a.target = "_blank";
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
};
|
|
||||||
|
|
||||||
const appendTextToEditor = (text) => {
|
|
||||||
const editor = editorRef.current;
|
|
||||||
const position = editor.getPosition();
|
|
||||||
const range = new monaco.Range(position.lineNumber, position.column, position.lineNumber, position.column);
|
|
||||||
editor.executeEdits('', [{
|
|
||||||
range: range,
|
|
||||||
text: "\n" + text,
|
|
||||||
forceMoveMarkers: true
|
|
||||||
}]);
|
|
||||||
resizeEditor();
|
|
||||||
};
|
|
||||||
|
|
||||||
const openFile = () => {
|
|
||||||
const fileInput = document.createElement('input');
|
|
||||||
fileInput.type = 'file';
|
|
||||||
fileInput.onchange = () => {
|
|
||||||
const file = fileInput.files[0];
|
|
||||||
|
|
||||||
if (!file)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const reader = new FileReader();
|
|
||||||
reader.onload = (e) => {
|
|
||||||
const fileName = file.name;
|
|
||||||
const ext = fileName.split('.').pop().toLowerCase();
|
|
||||||
const langMap = {
|
|
||||||
js: 'javascript', ts: 'typescript', html: 'html',
|
|
||||||
css: 'css', json: 'json', py: 'python', java: 'java',
|
|
||||||
c: 'c', cpp: 'cpp', cs: 'csharp', php: 'php',
|
|
||||||
rb: 'ruby', go: 'go', rs: 'rust'
|
|
||||||
};
|
|
||||||
const lang = langMap[ext] || 'plaintext';
|
|
||||||
|
|
||||||
monaco.editor.setModelLanguage(editorRef.current.getModel(), lang);
|
|
||||||
editorRef.current.setValue(e.target.result);
|
|
||||||
|
|
||||||
fileNameRef.current = fileName;
|
|
||||||
};
|
|
||||||
reader.readAsText(file);
|
|
||||||
};
|
|
||||||
fileInput.click();
|
|
||||||
};
|
|
||||||
|
|
||||||
const saveFile = () => {
|
|
||||||
const text = editorRef.current.getValue();
|
|
||||||
const fileName = prompt("Enter file name:", fileNameRef.current);
|
|
||||||
|
|
||||||
if (!fileName)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const blob = new Blob([text], { type: 'text/plain' });
|
|
||||||
const a = document.createElement('a');
|
|
||||||
a.href = URL.createObjectURL(blob);
|
|
||||||
a.download = fileNameRef.current;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
document.body.removeChild(a);
|
|
||||||
};
|
|
||||||
|
|
||||||
const sendMessageToCopilot = () => {
|
|
||||||
const promptMessage = prompt("Enter a prompt message:", '');
|
|
||||||
if (!promptMessage || promptMessage.trim() == '') {
|
|
||||||
alert("A prompt message is required.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
appendTextToEditor(`\n// ${promptMessage}... Generating text with Copilot...`);
|
|
||||||
pushPromptMessage("user", promptMessage);
|
|
||||||
|
|
||||||
(async () => {
|
|
||||||
const targetWsUrl = await getTargetByUrl('copilot.microsoft.com');
|
|
||||||
if (targetWsUrl) {
|
|
||||||
await _sendMessageToCopilot(targetWsUrl, promptMessage);
|
|
||||||
} else {
|
|
||||||
alert("Microsoft Copilot not running. Please visit copilot.microsoft.com first.");
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
};
|
|
||||||
|
|
||||||
const _sendMessageToCopilot = async (wsUrl, promptMessage) => {
|
|
||||||
const socket = new WebSocket(wsUrl);
|
|
||||||
const steps = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
method: 'Input.insertText',
|
|
||||||
params: {
|
|
||||||
text: promptMessage
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
method: 'Input.dispatchKeyEvent',
|
|
||||||
params: {
|
|
||||||
type: 'keyDown',
|
|
||||||
key: 'Enter',
|
|
||||||
code: 'Enter'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
method: 'Runtime.evaluate',
|
|
||||||
params: {
|
|
||||||
expression: '((e)=>e[e.length-1].querySelector("code")?.innerText||e[e.length-1].innerText)(document.querySelectorAll("[data-content=ai-message]"))'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
socket.onopen = () => {
|
|
||||||
steps.forEach((step) => {
|
|
||||||
if (step.id == 3) {
|
|
||||||
setTimeout(() => {
|
|
||||||
socket.send(JSON.stringify(step));
|
|
||||||
}, 9000);
|
|
||||||
} else {
|
|
||||||
socket.send(JSON.stringify(step));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
socket.onmessage = (event) => {
|
|
||||||
const response = JSON.parse(event.data);
|
|
||||||
console.log("Sent successfully:", response.result);
|
|
||||||
|
|
||||||
if (response.id == 3) {
|
|
||||||
const responseContent = response.result.result.value;
|
|
||||||
|
|
||||||
appendTextToEditor("/*\n" + responseContent + "\n*/");
|
|
||||||
pushPromptMessage("assistant", responseContent);
|
|
||||||
|
|
||||||
socket.close();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const getTargetByUrl = async (urlPart) => {
|
|
||||||
const response = await fetch(`${serverPrefix}devtools/json`);
|
|
||||||
const targets = await response.json();
|
|
||||||
|
|
||||||
const target = targets.find(target => target.url.includes(urlPart));
|
|
||||||
|
|
||||||
if (target) {
|
|
||||||
console.log(`Found target: ${target.title} (${target.id})`);
|
|
||||||
return target.webSocketDebuggerUrl;
|
|
||||||
} else {
|
|
||||||
console.log('Target not found');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const sendMessageToAzureAi = () => {
|
|
||||||
const promptMessage = prompt("Enter a prompt message:", '');
|
|
||||||
if (!promptMessage || promptMessage.trim() == '') {
|
|
||||||
alert("A prompt message is required.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
appendTextToEditor(`\n// ${promptMessage}... Generating text with Azure AI...`);
|
|
||||||
pushPromptMessage("user", promptMessage);
|
|
||||||
|
|
||||||
const apiKey = settingsRef.current.AzureAiServiceApiKey;
|
|
||||||
if (!apiKey || apiKey.trim() == '') {
|
|
||||||
alert("Azure AI API key is not set.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const url = `${settingsRef.current.AzureAiServicePrefix}models/chat/completions?api-version=${settingsRef.current.AzureAiServiceApiVersion}`;
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
messages: promptMessagesRef.current,
|
|
||||||
max_tokens: 2048,
|
|
||||||
temperature: 0.8,
|
|
||||||
top_p: 0.1,
|
|
||||||
presence_penalty: 0,
|
|
||||||
frequency_penalty: 0,
|
|
||||||
model: 'Phi-4'
|
|
||||||
};
|
|
||||||
|
|
||||||
axios.post(url, data, {
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'api-key': apiKey
|
|
||||||
}
|
|
||||||
}).then(response => {
|
|
||||||
response.data.choices.forEach(x => {
|
|
||||||
const responseContent = x.message.content;
|
|
||||||
pushPromptMessage("assistant", responseContent);
|
|
||||||
|
|
||||||
const responseText = DOMPurify.sanitize(responseContent, { ALLOWED_TAGS: [], ALLOWED_ATTR: [] });
|
|
||||||
appendTextToEditor(`/*\n${responseText}\n*/`);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Error:', error.response?.data || error.message);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const savePromptMessages = () => {
|
|
||||||
const text = JSON.stringify(promptMessagesRef.current, null, 4);
|
|
||||||
const blob = new Blob([text], { type: 'text/plain' });
|
|
||||||
const a = document.createElement('a');
|
|
||||||
a.href = URL.createObjectURL(blob);
|
|
||||||
a.download = "prompt.json";
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
document.body.removeChild(a);
|
|
||||||
};
|
|
||||||
|
|
||||||
const loadPromptMessages = () => {
|
|
||||||
const fileInput = document.createElement('input');
|
|
||||||
fileInput.type = 'file';
|
|
||||||
fileInput.accept = '.json';
|
|
||||||
fileInput.onchange = function (event) {
|
|
||||||
const file = event.target.files[0];
|
|
||||||
|
|
||||||
if (!file)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let reader = new FileReader();
|
|
||||||
reader.onload = function (e) {
|
|
||||||
promptMessagesRef.current = JSON.parse(e.target.result);
|
|
||||||
promptEditorRef.current.set(promptMessagesRef.current);
|
|
||||||
appendTextToEditor("\n//Prompt loaded successfully.");
|
|
||||||
};
|
|
||||||
reader.readAsText(file);
|
|
||||||
};
|
|
||||||
fileInput.click();
|
|
||||||
};
|
|
||||||
|
|
||||||
const queryWhois = () => {
|
|
||||||
const hostname = prompt("Enter a hostname or IP address:", '');
|
|
||||||
if (!hostname || hostname.trim() == '') {
|
|
||||||
appendTextToEditor("\n// A hostname or IP address is required.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
axios.get(`${serverPrefix}whois/${hostname}`).then(response => {
|
|
||||||
const responseText = DOMPurify.sanitize(response.data, { ALLOWED_TAGS: [], ALLOWED_ATTR: [] });
|
|
||||||
appendTextToEditor(`/*\nHostname:${hostname}\n\n${responseText}\n*/`);
|
|
||||||
pushPromptMessage("system", responseText);
|
|
||||||
}).catch(error => {
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const queryDns = () => {
|
|
||||||
const hostname = prompt("Enter a hostname or IP address:", '');
|
|
||||||
if (!hostname || hostname.trim() == '') {
|
|
||||||
appendTextToEditor("\n// A hostname or IP address is required.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
axios.get(`${serverPrefix}dns-query/${hostname}`).then(response => {
|
|
||||||
const responseText = response.data;
|
|
||||||
appendTextToEditor(`/*\nHostname:${hostname}\n\n${responseText}\n*/`);
|
|
||||||
pushPromptMessage("system", responseText);
|
|
||||||
}).catch(error => {
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const queryCiti = () => {
|
|
||||||
const hostname = prompt("Enter IP address:", '');
|
|
||||||
if (!hostname || hostname.trim() === '') {
|
|
||||||
appendTextToEditor("\n// IP address is required.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const apiKey = settingsRef.current.CitiApiKey;
|
|
||||||
if (!apiKey || apiKey.trim() === '') {
|
|
||||||
appendTextToEditor("\n// Criminal IP API key is not set.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const apiPrefix = settingsRef.current.CitiApiPrefix;
|
|
||||||
const ip = encodeURIComponent(hostname.trim());
|
|
||||||
|
|
||||||
axios.get(`${serverPrefix}citi-query/${hostname}`).then(response => {
|
|
||||||
const parser = new XMLParser();
|
|
||||||
const result = parser.parse(response.data);
|
|
||||||
const data = JSON.parse(result.json);
|
|
||||||
if (!data) {
|
|
||||||
appendTextToEditor("\n// No data returned from Criminal IP.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const lines = [];
|
|
||||||
lines.push(`/*\nCriminal IP Report: ${hostname}\n`);
|
|
||||||
|
|
||||||
// network port data
|
|
||||||
lines.push(`## Network ports:`);
|
|
||||||
if (data.port.data.length == 0) {
|
|
||||||
lines.push(`* No open ports found.`);
|
|
||||||
} else {
|
|
||||||
data.port.data.forEach(x => {
|
|
||||||
lines.push(`### ${x.open_port_no}/${x.socket}`);
|
|
||||||
lines.push(`* Application: ${x.app_name} ${x.app_version}`);
|
|
||||||
lines.push(`* Discovered hostnames: ${x.dns_names}`);
|
|
||||||
lines.push(`* Confirmed Time: ${x.confirmed_time}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// vulnerability data
|
|
||||||
lines.push(`## Vulnerabilities:`);
|
|
||||||
if (data.vulnerability.data.length == 0) {
|
|
||||||
lines.push(`* No vulnerabilities found.`);
|
|
||||||
} else {
|
|
||||||
data.vulnerability.data.forEach(x => {
|
|
||||||
lines.push(`### ${x.cve_id}`);
|
|
||||||
lines.push(`* ${x.cve_description}`);
|
|
||||||
lines.push(`* CVSSV2 Score: ${x.cvssv2_score}`);
|
|
||||||
lines.push(`* CVSSV3 Score: ${x.cvssv3_score}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
lines.push(`*/\n`);
|
|
||||||
const report = lines.join('\n');
|
|
||||||
|
|
||||||
appendTextToEditor(report);
|
|
||||||
pushPromptMessage("system", report);
|
|
||||||
}).catch(error => {
|
|
||||||
console.error(error);
|
|
||||||
appendTextToEditor(`\n// Failed to query Criminal IP: ${error.message}`);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
window.addEventListener('resize', () => {
|
|
||||||
resizeEditor();
|
|
||||||
});
|
|
||||||
window.dispatchEvent(new Event('resize'));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
fetchSettings();
|
|
||||||
|
|
||||||
return _e('div', { className: 'app' },
|
|
||||||
_e(RibbonMenu, {
|
|
||||||
onOpenFileClick: openFile,
|
|
||||||
onSaveFileClick: saveFile,
|
|
||||||
onCopliotClick: sendMessageToCopilot,
|
|
||||||
onAzureAiClick: sendMessageToAzureAi,
|
|
||||||
onSavePromptClick: savePromptMessages,
|
|
||||||
onLoadPromptClick: loadPromptMessages,
|
|
||||||
onQueryWhoisClick: queryWhois,
|
|
||||||
onQueryDnsClick: queryDns,
|
|
||||||
onQueryCitiClick: queryCiti
|
|
||||||
}),
|
|
||||||
_e('div', { id: 'container' },
|
|
||||||
_e(Editor, { editorRef }),
|
|
||||||
_e(PromptEditor, { promptEditorRef, promptMessagesRef })
|
|
||||||
),
|
|
||||||
_e('div', { className: 'banner' }, _e('a', { href: 'https://github.com/gnh1201/welsonjs' }, 'WelsonJS'), ' Editor powered by Metro UI, Monaco Editor, and JSONEditor.'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const container = document.getElementById('app');
|
|
||||||
const root = ReactDOM.createRoot(container);
|
|
||||||
root.render(_e(App));
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
4
WelsonJS.Toolkit/WelsonJS.Launcher/packages.config
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="System.IO.Compression.ZipFile" version="4.3.0" targetFramework="net472" />
|
||||||
|
</packages>
|
|
@ -3,9 +3,9 @@
|
||||||
// https://github.com/gnh1201/welsonjs
|
// https://github.com/gnh1201/welsonjs
|
||||||
using ClamAV.Net.Client;
|
using ClamAV.Net.Client;
|
||||||
using ClamAV.Net.Client.Results;
|
using ClamAV.Net.Client.Results;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics.Eventing.Reader;
|
using System.Diagnostics.Eventing.Reader;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.ServiceProcess;
|
using System.ServiceProcess;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@ namespace WelsonJS.Service
|
||||||
{
|
{
|
||||||
private EventLogWatcher eventLogWatcher;
|
private EventLogWatcher eventLogWatcher;
|
||||||
private ServiceMain parent;
|
private ServiceMain parent;
|
||||||
private ILogger logger;
|
|
||||||
private enum EventType: int
|
private enum EventType: int
|
||||||
{
|
{
|
||||||
FileCreate = 11,
|
FileCreate = 11,
|
||||||
|
@ -70,19 +69,18 @@ namespace WelsonJS.Service
|
||||||
private string clamAvConenctionString;
|
private string clamAvConenctionString;
|
||||||
private IClamAvClient clamAvClient;
|
private IClamAvClient clamAvClient;
|
||||||
|
|
||||||
public FileEventMonitor(ServiceBase _parent, string workingDirectory, ILogger _logger)
|
public FileEventMonitor(ServiceBase parent, string workingDirectory)
|
||||||
{
|
{
|
||||||
parent = (ServiceMain)_parent;
|
this.parent = (ServiceMain)parent;
|
||||||
logger = _logger;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
clamAvConenctionString = parent.ReadSettingsValue("CLAMAV_HOST");
|
clamAvConenctionString = this.parent.GetSettingsFileHandler().Read("CLAMAV_HOST", "Service");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
clamAvConenctionString = "tcp://127.0.0.1:3310";
|
clamAvConenctionString = "tcp://127.0.0.1:3310";
|
||||||
logger.LogInformation($"Failed to read the address because of {ex.Message}. Set default: {clamAvConenctionString}");
|
this.parent.Log($"Failed to read the address because of {ex.Message}. Set default: {clamAvConenctionString}");
|
||||||
}
|
}
|
||||||
ConnectToClamAv().Start();
|
ConnectToClamAv().Start();
|
||||||
}
|
}
|
||||||
|
@ -105,7 +103,7 @@ namespace WelsonJS.Service
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogInformation($"Could not reach to the Sysmon service: {ex.Message}");
|
parent.Log($"Could not reach to the Sysmon service: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,8 +140,8 @@ namespace WelsonJS.Service
|
||||||
string image = e.EventRecord.Properties[(int)FileCreateEvent.Image]?.Value?.ToString();
|
string image = e.EventRecord.Properties[(int)FileCreateEvent.Image]?.Value?.ToString();
|
||||||
string fileName = e.EventRecord.Properties[(int)FileCreateEvent.TargetFilename]?.Value?.ToString();
|
string fileName = e.EventRecord.Properties[(int)FileCreateEvent.TargetFilename]?.Value?.ToString();
|
||||||
|
|
||||||
logger.LogInformation($"> Detected the file creation: {fileName}");
|
parent.Log($"> Detected the file creation: {fileName}");
|
||||||
logger.LogInformation(parent.DispatchServiceEvent("fileCreated", new string[] {
|
parent.Log(parent.DispatchServiceEvent("fileCreated", new string[] {
|
||||||
ruleName,
|
ruleName,
|
||||||
processId,
|
processId,
|
||||||
image,
|
image,
|
||||||
|
@ -152,7 +150,7 @@ namespace WelsonJS.Service
|
||||||
|
|
||||||
if (clamAvClient != null)
|
if (clamAvClient != null)
|
||||||
{
|
{
|
||||||
logger.LogInformation($"> Starting the ClamAV scan: {fileName}");
|
parent.Log($"> Starting the ClamAV scan: {fileName}");
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
await ScanWithClamAv(fileName);
|
await ScanWithClamAv(fileName);
|
||||||
|
@ -172,8 +170,8 @@ namespace WelsonJS.Service
|
||||||
string desinationPort = e.EventRecord.Properties[(int)NetworkConnectionEvent.DestinationPort]?.Value?.ToString();
|
string desinationPort = e.EventRecord.Properties[(int)NetworkConnectionEvent.DestinationPort]?.Value?.ToString();
|
||||||
string dstinationAddress = $"{protocol}://{destinationIp}:{desinationPort}";
|
string dstinationAddress = $"{protocol}://{destinationIp}:{desinationPort}";
|
||||||
|
|
||||||
logger.LogInformation($"> Detected the network connection: {dstinationAddress}");
|
parent.Log($"> Detected the network connection: {dstinationAddress}");
|
||||||
logger.LogInformation(parent.DispatchServiceEvent("networkConnected", new string[] {
|
parent.Log(parent.DispatchServiceEvent("networkConnected", new string[] {
|
||||||
ruleName,
|
ruleName,
|
||||||
processId,
|
processId,
|
||||||
image,
|
image,
|
||||||
|
@ -193,8 +191,8 @@ namespace WelsonJS.Service
|
||||||
string eventType = e.EventRecord.Properties[(int)RegistryEvent.EventType]?.Value?.ToString();
|
string eventType = e.EventRecord.Properties[(int)RegistryEvent.EventType]?.Value?.ToString();
|
||||||
string targetObject = e.EventRecord.Properties[(int)RegistryEvent.TargetObject]?.Value?.ToString();
|
string targetObject = e.EventRecord.Properties[(int)RegistryEvent.TargetObject]?.Value?.ToString();
|
||||||
|
|
||||||
logger.LogInformation($"> Detected the registry modification: {targetObject}");
|
parent.Log($"> Detected the registry modification: {targetObject}");
|
||||||
logger.LogInformation(parent.DispatchServiceEvent("registryModified", new string[] {
|
parent.Log(parent.DispatchServiceEvent("registryModified", new string[] {
|
||||||
ruleName,
|
ruleName,
|
||||||
processId,
|
processId,
|
||||||
image,
|
image,
|
||||||
|
@ -211,12 +209,12 @@ namespace WelsonJS.Service
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogInformation($"Failed to process the event bacause of {ex.Message}.");
|
parent.Log($"Failed to process the event bacause of {ex.Message}.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.LogInformation("The event instance was null.");
|
parent.Log("The event instance was null.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,11 +230,11 @@ namespace WelsonJS.Service
|
||||||
// Get ClamAV engine and virus database version
|
// Get ClamAV engine and virus database version
|
||||||
VersionResult result = await clamAvClient.GetVersionAsync().ConfigureAwait(false);
|
VersionResult result = await clamAvClient.GetVersionAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
logger.LogInformation($"ClamAV version {result.ProgramVersion}, Virus database version {result.VirusDbVersion}");
|
parent.Log($"ClamAV version {result.ProgramVersion}, Virus database version {result.VirusDbVersion}");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogInformation($"Failed to read the address because of {ex.Message}. {clamAvConenctionString}");
|
parent.Log($"Failed to read the address because of {ex.Message}. {clamAvConenctionString}");
|
||||||
clamAvClient = null;
|
clamAvClient = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -245,8 +243,8 @@ namespace WelsonJS.Service
|
||||||
{
|
{
|
||||||
ScanResult res = await clamAvClient.ScanRemotePathAsync(remotePath).ConfigureAwait(false);
|
ScanResult res = await clamAvClient.ScanRemotePathAsync(remotePath).ConfigureAwait(false);
|
||||||
|
|
||||||
logger.LogInformation($"> Scan result: Infected={res.Infected}, VirusName={res.VirusName}");
|
parent.Log($"> Scan result: Infected={res.Infected}, VirusName={res.VirusName}");
|
||||||
logger.LogInformation(parent.DispatchServiceEvent("avScanResult", new string[] {
|
parent.Log(parent.DispatchServiceEvent("avScanResult", new string[] {
|
||||||
res.Infected.ToString(),
|
res.Infected.ToString(),
|
||||||
res.VirusName
|
res.VirusName
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -9,30 +9,25 @@ using System.ServiceProcess;
|
||||||
using Grpc.Net.Client;
|
using Grpc.Net.Client;
|
||||||
using Grpc.Net.Client.Web;
|
using Grpc.Net.Client.Web;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace WelsonJS.Service
|
namespace WelsonJS.Service
|
||||||
{
|
{
|
||||||
public class HeartbeatClient
|
public class HeartbeatClient
|
||||||
{
|
{
|
||||||
private readonly HeartbeatService.HeartbeatServiceClient _client;
|
private readonly HeartbeatService.HeartbeatServiceClient _client;
|
||||||
private ILogger logger;
|
|
||||||
private readonly GrpcChannel _channel;
|
private readonly GrpcChannel _channel;
|
||||||
private int HeartbeatInterval;
|
private const int HeartbeatInterval = 2000; // 2 seconds
|
||||||
private ServiceMain parent;
|
private ServiceMain _parent;
|
||||||
private string clientId;
|
private string clientId;
|
||||||
private string serverAddress;
|
private string serverAddress;
|
||||||
|
|
||||||
public HeartbeatClient(ServiceBase _parent, ILogger _logger)
|
public HeartbeatClient(ServiceBase parent)
|
||||||
{
|
{
|
||||||
parent = (ServiceMain)_parent;
|
_parent = (ServiceMain)parent;
|
||||||
logger = _logger;
|
|
||||||
|
|
||||||
HeartbeatInterval = int.Parse(parent.ReadSettingsValue("HEARTBEAT_INTERVAL") ?? "2000");
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
serverAddress = parent.ReadSettingsValue("GRPC_HOST");
|
serverAddress = _parent.GetSettingsFileHandler().Read("GRPC_HOST", "Service");
|
||||||
if (String.IsNullOrEmpty(serverAddress))
|
if (String.IsNullOrEmpty(serverAddress))
|
||||||
{
|
{
|
||||||
throw new Exception("The server address could not be empty.");
|
throw new Exception("The server address could not be empty.");
|
||||||
|
@ -41,7 +36,7 @@ namespace WelsonJS.Service
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
serverAddress = "http://localhost:50051";
|
serverAddress = "http://localhost:50051";
|
||||||
logger.LogInformation($"Failed to read the address because of {ex.Message}. Set default: {serverAddress}");
|
_parent.Log($"Failed to read the address because of {ex.Message}. Set default: {serverAddress}");
|
||||||
}
|
}
|
||||||
|
|
||||||
var httpClientHandler = new HttpClientHandler();
|
var httpClientHandler = new HttpClientHandler();
|
||||||
|
@ -54,7 +49,7 @@ namespace WelsonJS.Service
|
||||||
_client = new HeartbeatService.HeartbeatServiceClient(_channel);
|
_client = new HeartbeatService.HeartbeatServiceClient(_channel);
|
||||||
|
|
||||||
clientId = GetSystemUUID().ToLower();
|
clientId = GetSystemUUID().ToLower();
|
||||||
logger.LogInformation($"Use the client ID: {clientId}");
|
_parent.Log($"Use the client ID: {clientId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task StartHeartbeatAsync()
|
public async Task StartHeartbeatAsync()
|
||||||
|
@ -72,14 +67,14 @@ namespace WelsonJS.Service
|
||||||
|
|
||||||
await call.RequestStream.WriteAsync(request);
|
await call.RequestStream.WriteAsync(request);
|
||||||
await call.RequestStream.CompleteAsync();
|
await call.RequestStream.CompleteAsync();
|
||||||
logger.LogInformation("Sent heartbeat");
|
_parent.Log("Sent heartbeat");
|
||||||
|
|
||||||
await Task.Delay(HeartbeatInterval); // Wait for HeartbeatInterval
|
await Task.Delay(HeartbeatInterval); // HeartbeatInterval 동안 대기
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogInformation("Heartbeat request stream failed: " + ex.Message);
|
_parent.Log("Heartbeat request stream failed: " + ex.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 서버 응답을 수신하는 작업
|
// 서버 응답을 수신하는 작업
|
||||||
|
@ -88,16 +83,16 @@ namespace WelsonJS.Service
|
||||||
while (await call.ResponseStream.MoveNext())
|
while (await call.ResponseStream.MoveNext())
|
||||||
{
|
{
|
||||||
var response = call.ResponseStream.Current;
|
var response = call.ResponseStream.Current;
|
||||||
logger.LogInformation("Heartbeat response received: " + response.IsAlive);
|
_parent.Log("Heartbeat response received: " + response.IsAlive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (RpcException ex)
|
catch (RpcException ex)
|
||||||
{
|
{
|
||||||
logger.LogInformation($"gRPC error: {ex.Status.Detail}");
|
_parent.Log($"gRPC error: {ex.Status.Detail}");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogInformation($"Unexpected error: {ex.Message}");
|
_parent.Log($"Unexpected error: {ex.Message}");
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -121,7 +116,7 @@ namespace WelsonJS.Service
|
||||||
while (await eventCall.ResponseStream.MoveNext())
|
while (await eventCall.ResponseStream.MoveNext())
|
||||||
{
|
{
|
||||||
var response = eventCall.ResponseStream.Current;
|
var response = eventCall.ResponseStream.Current;
|
||||||
logger.LogInformation($"Received event from server: {response.EventType} with args: {string.Join(", ", response.Args)}");
|
_parent.Log($"Received event from server: {response.EventType} with args: {string.Join(", ", response.Args)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
@ -151,7 +146,7 @@ namespace WelsonJS.Service
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogInformation($"An error occurred while retrieving the system UUID: {ex.Message}");
|
_parent.Log($"An error occurred while retrieving the system UUID: {ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using System.IO;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace WelsonJS.Service.Logging
|
|
||||||
{
|
|
||||||
public class FileLogger : ILogger
|
|
||||||
{
|
|
||||||
private string loggingDirectory;
|
|
||||||
private string categoryName;
|
|
||||||
private static object _lock = new object();
|
|
||||||
|
|
||||||
public FileLogger(string _loggingDirectory, string _categoryName = "welsonjs")
|
|
||||||
{
|
|
||||||
loggingDirectory = _loggingDirectory;
|
|
||||||
categoryName = _categoryName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IDisposable BeginScope<TState>(TState state)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsEnabled(LogLevel logLevel)
|
|
||||||
{
|
|
||||||
//return logLevel == LogLevel.Trace;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
|
|
||||||
{
|
|
||||||
if (formatter != null)
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!Directory.Exists(loggingDirectory))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(loggingDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
string path = Path.Combine(loggingDirectory, $"{categoryName}_service.{DateTime.Now.ToString("yyyy-MM-dd")}.log");
|
|
||||||
string nl = Environment.NewLine;
|
|
||||||
string err = "";
|
|
||||||
|
|
||||||
if (exception != null)
|
|
||||||
{
|
|
||||||
err = nl + exception.GetType() + ": " + exception.Message + nl + exception.StackTrace + nl;
|
|
||||||
}
|
|
||||||
|
|
||||||
File.AppendAllText(path, logLevel.ToString() + ": [" + DateTime.Now.ToString() + "] " + formatter(state, exception) + nl + err);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine(LogLevel.Warning.ToString() + ": [" + DateTime.Now.ToString() + "] Failed to write a log file. " + ex.Message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace WelsonJS.Service.Logging
|
|
||||||
{
|
|
||||||
public static class FileLoggerExtensions
|
|
||||||
{
|
|
||||||
public static ILoggerFactory AddDirectory(this ILoggerFactory factory, string loggingDirectory)
|
|
||||||
{
|
|
||||||
factory.AddProvider(new FileLoggerProvider(loggingDirectory));
|
|
||||||
return factory;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace WelsonJS.Service.Logging
|
|
||||||
{
|
|
||||||
public class FileLoggerProvider : ILoggerProvider
|
|
||||||
{
|
|
||||||
private string loggingDirectory;
|
|
||||||
|
|
||||||
public FileLoggerProvider(string _loggingDirectory)
|
|
||||||
{
|
|
||||||
loggingDirectory = _loggingDirectory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ILogger CreateLogger(string categoryName)
|
|
||||||
{
|
|
||||||
return new FileLogger(loggingDirectory, categoryName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
// Dispose
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +1,17 @@
|
||||||
using Microsoft.Extensions.Logging;
|
using System;
|
||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.ServiceProcess;
|
using System.ServiceProcess;
|
||||||
using WelsonJS.Service.Logging;
|
using System.Text;
|
||||||
|
|
||||||
namespace WelsonJS.Service
|
namespace WelsonJS.Service
|
||||||
{
|
{
|
||||||
internal static class Program
|
internal static class Program
|
||||||
{
|
{
|
||||||
private static ILogger logger;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 해당 애플리케이션의 주 진입점입니다.
|
/// 해당 애플리케이션의 주 진입점입니다.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
///
|
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
// create the logger
|
|
||||||
ILoggerFactory factory = LoggerFactory.Create(builder => builder.AddConsole());
|
|
||||||
factory.AddDirectory(Path.GetTempPath());
|
|
||||||
logger = factory.CreateLogger("welsonjs");
|
|
||||||
|
|
||||||
// create the service
|
|
||||||
if (Environment.UserInteractive)
|
if (Environment.UserInteractive)
|
||||||
{
|
{
|
||||||
Console.WriteLine("WelsonJS Service Application (User Interactive Mode)");
|
Console.WriteLine("WelsonJS Service Application (User Interactive Mode)");
|
||||||
|
@ -29,7 +19,7 @@ namespace WelsonJS.Service
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
Console.WriteLine("Service is running...");
|
Console.WriteLine("Service is running...");
|
||||||
|
|
||||||
ServiceMain svc = new ServiceMain(args, logger);
|
ServiceMain svc = new ServiceMain(args);
|
||||||
svc.TestStartupAndStop();
|
svc.TestStartupAndStop();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -37,27 +27,10 @@ namespace WelsonJS.Service
|
||||||
ServiceBase[] ServicesToRun;
|
ServiceBase[] ServicesToRun;
|
||||||
ServicesToRun = new ServiceBase[]
|
ServicesToRun = new ServiceBase[]
|
||||||
{
|
{
|
||||||
new ServiceMain(args, logger)
|
new ServiceMain(args)
|
||||||
};
|
};
|
||||||
ServiceBase.Run(ServicesToRun);
|
ServiceBase.Run(ServicesToRun);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetAppDataPath()
|
|
||||||
{
|
|
||||||
string path = Path.Combine(
|
|
||||||
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
|
|
||||||
"WelsonJS"
|
|
||||||
);
|
|
||||||
|
|
||||||
Directory.CreateDirectory(path);
|
|
||||||
|
|
||||||
if (!Directory.Exists(path))
|
|
||||||
{
|
|
||||||
throw new IOException("Failed to create directory: " + path);
|
|
||||||
}
|
|
||||||
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,11 @@ using System.Runtime.InteropServices;
|
||||||
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
|
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
|
||||||
// 이러한 특성 값을 변경하세요.
|
// 이러한 특성 값을 변경하세요.
|
||||||
[assembly: AssemblyTitle("WelsonJS.Service")]
|
[assembly: AssemblyTitle("WelsonJS.Service")]
|
||||||
[assembly: AssemblyDescription("Windows Service for WelsonJS framework based applications")]
|
[assembly: AssemblyDescription("Windows Service for WelsonJS framework")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("Catswords")]
|
[assembly: AssemblyCompany("Catswords")]
|
||||||
[assembly: AssemblyProduct("WelsonJS")]
|
[assembly: AssemblyProduct("WelsonJS")]
|
||||||
[assembly: AssemblyCopyright("Catswords OSS, GPLv3 or Ms-RL")]
|
[assembly: AssemblyCopyright("Catswords OSS, C-2021-000237, Opensource licensed under GPLv3 or MS-RL")]
|
||||||
[assembly: AssemblyTrademark("WelsonJS")]
|
[assembly: AssemblyTrademark("WelsonJS")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||||
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
|
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
|
||||||
// 기본값으로 할 수 있습니다.
|
// 기본값으로 할 수 있습니다.
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("0.2.7.54")]
|
[assembly: AssemblyVersion("0.2.7.26")]
|
||||||
[assembly: AssemblyFileVersion("0.2.7.54")]
|
[assembly: AssemblyFileVersion("0.2.7.26")]
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// ScreenMatching.cs
|
// ScreenMatching.cs
|
||||||
// https://github.com/gnh1201/welsonjs
|
// https://github.com/gnh1201/welsonjs
|
||||||
// https://catswords-oss.rdbl.io/5719744820/8803957194
|
// https://github.com/gnh1201/welsonjs/wiki/Screen-Time-Feature
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
@ -15,7 +15,6 @@ using System.Windows.Forms;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Tesseract;
|
using Tesseract;
|
||||||
using WelsonJS.Service;
|
using WelsonJS.Service;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
public class ScreenMatch
|
public class ScreenMatch
|
||||||
{
|
{
|
||||||
|
@ -106,14 +105,13 @@ public class ScreenMatch
|
||||||
}
|
}
|
||||||
|
|
||||||
private ServiceMain parent;
|
private ServiceMain parent;
|
||||||
private ILogger logger;
|
|
||||||
private List<Bitmap> templateImages;
|
private List<Bitmap> templateImages;
|
||||||
private string templateDirectoryPath;
|
private string templateDirectoryPath;
|
||||||
private string outputDirectoryPath;
|
private string outputDirectoryPath;
|
||||||
private int templateCurrentIndex = 0;
|
private int templateCurrentIndex = 0;
|
||||||
private double threshold = 0.3;
|
private double threshold = 0.4;
|
||||||
private string mode;
|
private string mode;
|
||||||
private bool busy;
|
private bool busy = false;
|
||||||
private List<string> _params = new List<string>();
|
private List<string> _params = new List<string>();
|
||||||
private bool isSearchFromEnd = false;
|
private bool isSearchFromEnd = false;
|
||||||
private bool isSaveToFile = false;
|
private bool isSaveToFile = false;
|
||||||
|
@ -125,62 +123,14 @@ public class ScreenMatch
|
||||||
private List<string> sampleOcr;
|
private List<string> sampleOcr;
|
||||||
private List<string> sampleNodup;
|
private List<string> sampleNodup;
|
||||||
private Size sampleNodupSize;
|
private Size sampleNodupSize;
|
||||||
private Queue<Bitmap> outdatedSamples;
|
private Queue<Bitmap> sampleOutdated;
|
||||||
|
private byte thresholdConvertToBinary = 191;
|
||||||
private string tesseractDataPath;
|
private string tesseractDataPath;
|
||||||
private string tesseractLanguage;
|
private string tesseractLanguage;
|
||||||
|
|
||||||
private void SetBusy(bool busy)
|
public ScreenMatch(ServiceBase parent, string workingDirectory)
|
||||||
{
|
{
|
||||||
this.busy = busy;
|
this.parent = (ServiceMain)parent;
|
||||||
logger.LogInformation($"State changed: busy={busy}");
|
|
||||||
}
|
|
||||||
|
|
||||||
private decimal GetScreenScalingFactor(Screen screen)
|
|
||||||
{
|
|
||||||
DEVMODE dm = new DEVMODE();
|
|
||||||
dm.dmSize = (short)Marshal.SizeOf(typeof(DEVMODE));
|
|
||||||
EnumDisplaySettings(screen.DeviceName, -1, ref dm);
|
|
||||||
|
|
||||||
decimal scalingFactor = Math.Round(Decimal.Divide(dm.dmPelsWidth, screen.Bounds.Width), 2);
|
|
||||||
if (scalingFactor > 1)
|
|
||||||
{
|
|
||||||
logger.LogInformation($"Screen with scaling detected: {scalingFactor}x");
|
|
||||||
logger.LogWarning("Please check the screen DPI.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return scalingFactor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TemplateInfo
|
|
||||||
{
|
|
||||||
public string FileName { get; set; }
|
|
||||||
public int Index { get; set; }
|
|
||||||
|
|
||||||
public TemplateInfo(string fileName, int index)
|
|
||||||
{
|
|
||||||
FileName = fileName;
|
|
||||||
Index = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class SampleInfo
|
|
||||||
{
|
|
||||||
public string FileName { get; set; }
|
|
||||||
public uint Crc32 { get; set; }
|
|
||||||
|
|
||||||
public SampleInfo(string fileName, uint crc32)
|
|
||||||
{
|
|
||||||
FileName = fileName;
|
|
||||||
Crc32 = crc32;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ScreenMatch(ServiceBase _parent, string workingDirectory, ILogger _logger)
|
|
||||||
{
|
|
||||||
parent = (ServiceMain)_parent;
|
|
||||||
logger = _logger;
|
|
||||||
|
|
||||||
SetBusy(false);
|
|
||||||
|
|
||||||
templateDirectoryPath = Path.Combine(workingDirectory, "app/assets/img/_templates");
|
templateDirectoryPath = Path.Combine(workingDirectory, "app/assets/img/_templates");
|
||||||
outputDirectoryPath = Path.Combine(workingDirectory, "app/assets/img/_captured");
|
outputDirectoryPath = Path.Combine(workingDirectory, "app/assets/img/_captured");
|
||||||
|
@ -200,24 +150,24 @@ public class ScreenMatch
|
||||||
sampleNodup = new List<string>();
|
sampleNodup = new List<string>();
|
||||||
sampleNodupSize = new Size
|
sampleNodupSize = new Size
|
||||||
{
|
{
|
||||||
Width = 180,
|
Width = 256,
|
||||||
Height = 60
|
Height = 32
|
||||||
};
|
};
|
||||||
outdatedSamples = new Queue<Bitmap>();
|
sampleOutdated = new Queue<Bitmap>();
|
||||||
|
|
||||||
// Read values from configration file
|
// Read values from configration file
|
||||||
string screen_time_mode;
|
string screen_time_mode;
|
||||||
string screen_time_params;
|
string screen_time_params;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
screen_time_mode = parent.ReadSettingsValue("SCREEN_TIME_MODE");
|
screen_time_mode = this.parent.GetSettingsFileHandler().Read("SCREEN_TIME_MODE", "Service");
|
||||||
screen_time_params = parent.ReadSettingsValue("SCREEN_TIME_PARAMS");
|
screen_time_params = this.parent.GetSettingsFileHandler().Read("SCREEN_TIME_PARAMS", "Service");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
screen_time_mode = null;
|
screen_time_mode = null;
|
||||||
screen_time_params = null;
|
screen_time_params = null;
|
||||||
logger.LogInformation($"Failed to read from configration file: {ex.Message}");
|
this.parent.Log($"Failed to read from configration file: {ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!String.IsNullOrEmpty(screen_time_params))
|
if (!String.IsNullOrEmpty(screen_time_params))
|
||||||
|
@ -257,21 +207,14 @@ public class ScreenMatch
|
||||||
case "backward":
|
case "backward":
|
||||||
{
|
{
|
||||||
isSearchFromEnd = true;
|
isSearchFromEnd = true;
|
||||||
logger.LogInformation("Use the backward search when screen time");
|
this.parent.Log("Use the backward search when screen time");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case "save":
|
case "save":
|
||||||
{
|
{
|
||||||
isSaveToFile = true;
|
isSaveToFile = true;
|
||||||
logger.LogInformation("Will be save an image file when capture the screens");
|
this.parent.Log("Will be save an image file when capture the screens");
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "threshold":
|
|
||||||
{
|
|
||||||
double.TryParse(config_value, out double t);
|
|
||||||
threshold = t;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,20 +246,6 @@ public class ScreenMatch
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case "sample_nodup_width":
|
|
||||||
{
|
|
||||||
int.TryParse(config_value, out int w);
|
|
||||||
sampleNodupSize.Width = w;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "sample_nodup_height":
|
|
||||||
{
|
|
||||||
int.TryParse(config_value, out int h);
|
|
||||||
sampleNodupSize.Height = h;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case "sample_adjust_x":
|
case "sample_adjust_x":
|
||||||
{
|
{
|
||||||
int.TryParse(config_value, out sampleAdjustX);
|
int.TryParse(config_value, out sampleAdjustX);
|
||||||
|
@ -377,27 +306,13 @@ public class ScreenMatch
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
files = new string[]{};
|
files = new string[]{};
|
||||||
logger.LogInformation($"Failed to read the directory structure: {ex.Message}");
|
parent.Log($"Failed to read the directory structure: {ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
{
|
{
|
||||||
string filename = Path.GetFileName(file);
|
string filename = Path.GetFileName(file);
|
||||||
|
Bitmap bitmap = new Bitmap(file)
|
||||||
string realpath;
|
|
||||||
string altpath = parent.GetUserVariablesHandler().GetValue(filename);
|
|
||||||
if (!String.IsNullOrEmpty(altpath))
|
|
||||||
{
|
|
||||||
realpath = altpath;
|
|
||||||
logger.LogInformation($"Use the alternative image: {realpath}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
realpath = file;
|
|
||||||
logger.LogInformation($"Use the default image: {realpath}");
|
|
||||||
}
|
|
||||||
|
|
||||||
Bitmap bitmap = new Bitmap(realpath)
|
|
||||||
{
|
{
|
||||||
Tag = filename
|
Tag = filename
|
||||||
};
|
};
|
||||||
|
@ -406,7 +321,7 @@ public class ScreenMatch
|
||||||
{
|
{
|
||||||
if (filename.StartsWith("binary_"))
|
if (filename.StartsWith("binary_"))
|
||||||
{
|
{
|
||||||
templateImages.Add(ImageQuantize(bitmap));
|
templateImages.Add(ConvertToBinary(bitmap, thresholdConvertToBinary));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -428,22 +343,22 @@ public class ScreenMatch
|
||||||
|
|
||||||
if (templateImages.Count > 0)
|
if (templateImages.Count > 0)
|
||||||
{
|
{
|
||||||
SetBusy(true);
|
toggleBusy();
|
||||||
|
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case "screen": // 화면 기준
|
case "screen": // 화면 기준
|
||||||
results = CaptureAndMatchAllScreens();
|
results = CaptureAndMatchAllScreens();
|
||||||
SetBusy(false);
|
toggleBusy();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "window": // 윈도우 핸들 기준
|
case "window": // 윈도우 핸들 기준
|
||||||
results = CaptureAndMatchAllWindows();
|
results = CaptureAndMatchAllWindows();
|
||||||
SetBusy(false);
|
toggleBusy();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
SetBusy(false);
|
toggleBusy();
|
||||||
throw new Exception($"Unknown capture mode {mode}");
|
throw new Exception($"Unknown capture mode {mode}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -461,96 +376,42 @@ public class ScreenMatch
|
||||||
Screen screen = Screen.AllScreens[i];
|
Screen screen = Screen.AllScreens[i];
|
||||||
Bitmap mainImage = CaptureScreen(screen);
|
Bitmap mainImage = CaptureScreen(screen);
|
||||||
|
|
||||||
Bitmap templateImage = templateImages[templateCurrentIndex];
|
if (isSaveToFile)
|
||||||
string templateName = templateImage.Tag as string;
|
{
|
||||||
TemplateInfo nextTemplateInfo = parent.GetNextTemplateInfo();
|
string outputFilePath = Path.Combine(outputDirectoryPath, $"{DateTime.Now.ToString("yyyy-MM-dd hh mm ss")}.png");
|
||||||
|
((Bitmap)mainImage.Clone()).Save(outputFilePath);
|
||||||
|
parent.Log($"Screenshot saved: {outputFilePath}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Bitmap image = templateImages[templateCurrentIndex];
|
||||||
|
string templateName = image.Tag as string;
|
||||||
|
string nextTemplateName = parent.GetNextTemplateName();
|
||||||
|
|
||||||
Size templateSize = new Size
|
Size templateSize = new Size
|
||||||
{
|
{
|
||||||
Width = templateImage.Width,
|
Width = image.Width,
|
||||||
Height = templateImage.Height
|
Height = image.Height
|
||||||
};
|
};
|
||||||
|
|
||||||
logger.LogInformation($"Trying match the template {templateName} on the screen {i}...");
|
parent.Log($"Trying match the template {templateName} on the screen {i}...");
|
||||||
|
|
||||||
if (!String.IsNullOrEmpty(nextTemplateInfo.FileName) && templateName != nextTemplateInfo.FileName)
|
if (!String.IsNullOrEmpty(nextTemplateName) && templateName != nextTemplateName)
|
||||||
{
|
{
|
||||||
logger.LogInformation($"Ignored the template {templateName}");
|
parent.Log($"Ignored the template {templateName}");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bitmap out_mainImage;
|
Bitmap _mainImage;
|
||||||
string out_filename;
|
|
||||||
if (templateName.StartsWith("binary_"))
|
if (templateName.StartsWith("binary_"))
|
||||||
{
|
{
|
||||||
out_mainImage = ImageQuantize((Bitmap)mainImage.Clone());
|
_mainImage = ConvertToBinary((Bitmap)mainImage.Clone(), thresholdConvertToBinary);
|
||||||
out_filename = $"{DateTime.Now:yyyy-MM-dd hh mm ss} binary.png";
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
out_mainImage = mainImage;
|
_mainImage = mainImage;
|
||||||
out_filename = $"{DateTime.Now:yyyy-MM-dd hh mm ss}.png";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isSaveToFile)
|
|
||||||
{
|
|
||||||
string out_filepath = Path.Combine(outputDirectoryPath, out_filename);
|
|
||||||
((Bitmap)out_mainImage.Clone()).Save(out_filepath);
|
|
||||||
logger.LogInformation($"Screenshot saved: {out_filepath}");
|
|
||||||
}
|
|
||||||
|
|
||||||
// List to store the positions of matched templates in the main image
|
|
||||||
List<Point> matchPositions;
|
|
||||||
|
|
||||||
// If the index value is negative, retrieve and use an outdated image from the queue
|
|
||||||
if (nextTemplateInfo.Index < 0)
|
|
||||||
{
|
|
||||||
logger.LogInformation($"Finding a previous screen of {nextTemplateInfo.FileName}...");
|
|
||||||
|
|
||||||
Bitmap outdatedImage = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Since outdatedSamples is also used to detect duplicate work, we do not delete tasks with Dequeue.
|
|
||||||
foreach (var image in outdatedSamples)
|
|
||||||
{
|
|
||||||
if (image.Tag != null &&
|
|
||||||
((SampleInfo)image.Tag).FileName == nextTemplateInfo.FileName)
|
|
||||||
{
|
|
||||||
outdatedImage = image;
|
|
||||||
logger.LogInformation($"Found the previous screen of {nextTemplateInfo.FileName}");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
logger.LogInformation($"Error finding a previous screen: {ex.Message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the matching positions of the outdated image in the main image
|
|
||||||
if (outdatedImage != null) {
|
|
||||||
matchPositions = FindTemplate(out_mainImage, outdatedImage);
|
|
||||||
if (matchPositions.Count > 0)
|
|
||||||
{
|
|
||||||
logger.LogInformation("Match found with the outdated image");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logger.LogInformation("No match found with the outdated image");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logger.LogInformation("No match found an outdated image");
|
|
||||||
matchPositions = new List<Point>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If the index is not negative, use the current image for template matching
|
|
||||||
matchPositions = FindTemplate(out_mainImage, (Bitmap)templateImage.Clone());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Point> matchPositions = FindTemplate(_mainImage, (Bitmap)image.Clone());
|
||||||
foreach (Point matchPosition in matchPositions)
|
foreach (Point matchPosition in matchPositions)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -570,18 +431,18 @@ public class ScreenMatch
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogInformation($"Ignore the match. {ex.Message}");
|
parent.Log($"Ignore the match. {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (results.Count > 0)
|
if (results.Count > 0)
|
||||||
{
|
{
|
||||||
logger.LogInformation("Match found");
|
parent.Log("Match found");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.LogInformation($"No match found");
|
parent.Log($"No match found");
|
||||||
}
|
}
|
||||||
|
|
||||||
templateCurrentIndex = ++templateCurrentIndex % templateImages.Count;
|
templateCurrentIndex = ++templateCurrentIndex % templateImages.Count;
|
||||||
|
@ -629,34 +490,34 @@ public class ScreenMatch
|
||||||
{
|
{
|
||||||
Bitmap croppedNodupBitmap = CropBitmap(bitmap, matchPosition, templateSize, sampleNodupSize);
|
Bitmap croppedNodupBitmap = CropBitmap(bitmap, matchPosition, templateSize, sampleNodupSize);
|
||||||
uint bitmapCrc32 = ComputeBitmapCrc32(croppedNodupBitmap);
|
uint bitmapCrc32 = ComputeBitmapCrc32(croppedNodupBitmap);
|
||||||
croppedNodupBitmap.Tag = new SampleInfo(templateName, bitmapCrc32);
|
croppedNodupBitmap.Tag = bitmapCrc32;
|
||||||
|
|
||||||
bool bitmapExists = outdatedSamples.Any(x => ((SampleInfo)x.Tag).Crc32 == bitmapCrc32);
|
bool bitmapExists = sampleOutdated.Any(x => (uint)x.Tag == bitmapCrc32);
|
||||||
if (bitmapExists)
|
if (bitmapExists)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"This may be a duplicate request. {templateName}");
|
throw new InvalidOperationException($"This may be a duplicate request. {templateName}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
outdatedSamples.Enqueue(croppedNodupBitmap);
|
sampleOutdated.Enqueue(croppedNodupBitmap);
|
||||||
logger.LogInformation($"Added to the image queue. {templateName}");
|
parent.Log($"Added to the image queue. {templateName}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if use Clipboard
|
// if use Clipboard
|
||||||
if (sampleClipboard.Contains(templateName))
|
if (sampleClipboard.Contains(templateName))
|
||||||
{
|
{
|
||||||
logger.LogInformation($"Trying to use the clipboard... {templateName}");
|
parent.Log($"Trying to use the clipboard... {templateName}");
|
||||||
Thread th = new Thread(new ThreadStart(() =>
|
Thread th = new Thread(new ThreadStart(() =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Clipboard.SetImage((Bitmap)croppedBitmap.Clone());
|
Clipboard.SetImage((Bitmap)croppedBitmap.Clone());
|
||||||
logger.LogInformation($"Copied the image to Clipboard");
|
parent.Log($"Copied the image to Clipboard");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogInformation($"Failed to copy to the clipboard: {ex.Message}");
|
parent.Log($"Failed to copy to the clipboard: {ex.Message}");
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
th.SetApartmentState(ApartmentState.STA);
|
th.SetApartmentState(ApartmentState.STA);
|
||||||
|
@ -674,14 +535,14 @@ public class ScreenMatch
|
||||||
{
|
{
|
||||||
text = page.GetText();
|
text = page.GetText();
|
||||||
|
|
||||||
logger.LogInformation($"Mean confidence: {page.GetMeanConfidence()}");
|
parent.Log($"Mean confidence: {page.GetMeanConfidence()}");
|
||||||
logger.LogInformation($"Text (GetText): {text}");
|
parent.Log($"Text (GetText): {text}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogInformation($"Failed to OCR: {ex.Message}");
|
parent.Log($"Failed to OCR: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -691,7 +552,13 @@ public class ScreenMatch
|
||||||
public Bitmap CaptureScreen(Screen screen)
|
public Bitmap CaptureScreen(Screen screen)
|
||||||
{
|
{
|
||||||
Rectangle screenSize = screen.Bounds;
|
Rectangle screenSize = screen.Bounds;
|
||||||
decimal scalingFactor = GetScreenScalingFactor(screen);
|
|
||||||
|
DEVMODE dm = new DEVMODE();
|
||||||
|
dm.dmSize = (short)Marshal.SizeOf(typeof(DEVMODE));
|
||||||
|
EnumDisplaySettings(screen.DeviceName, -1, ref dm);
|
||||||
|
|
||||||
|
var scalingFactor = Math.Round(Decimal.Divide(dm.dmPelsWidth, screen.Bounds.Width), 2);
|
||||||
|
parent.Log($"Resolved the screen scale: {scalingFactor}");
|
||||||
|
|
||||||
int adjustedWidth = (int)(screenSize.Width * scalingFactor);
|
int adjustedWidth = (int)(screenSize.Width * scalingFactor);
|
||||||
int adjustedHeight = (int)(screenSize.Height * scalingFactor);
|
int adjustedHeight = (int)(screenSize.Height * scalingFactor);
|
||||||
|
@ -754,13 +621,13 @@ public class ScreenMatch
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogInformation($"Ignore the match. {ex.Message}");
|
parent.Log($"Ignore the match. {ex.Message}");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
logger.LogInformation($"Error {ex.Message}");
|
parent.Log($"Error {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -839,6 +706,11 @@ public class ScreenMatch
|
||||||
return matches;
|
return matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void toggleBusy()
|
||||||
|
{
|
||||||
|
busy = !busy;
|
||||||
|
}
|
||||||
|
|
||||||
private bool IsTemplateMatch(Bitmap mainImage, Bitmap templateImage, int offsetX, int offsetY, double threshold)
|
private bool IsTemplateMatch(Bitmap mainImage, Bitmap templateImage, int offsetX, int offsetY, double threshold)
|
||||||
{
|
{
|
||||||
int templateWidth = templateImage.Width;
|
int templateWidth = templateImage.Width;
|
||||||
|
@ -881,16 +753,14 @@ public class ScreenMatch
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Bitmap ImageQuantize(Bitmap image, int levels = 4)
|
private Bitmap ConvertToBinary(Bitmap image, byte threshold)
|
||||||
{
|
{
|
||||||
Bitmap quantizedImage = new Bitmap(image.Width, image.Height);
|
Bitmap binaryImage = new Bitmap(image.Width, image.Height);
|
||||||
if (image.Tag != null)
|
if (image.Tag != null)
|
||||||
{
|
{
|
||||||
quantizedImage.Tag = image.Tag;
|
binaryImage.Tag = image.Tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
int step = 255 / (levels - 1); // step by step..... ooh baby...(?)
|
|
||||||
|
|
||||||
for (int y = 0; y < image.Height; y++)
|
for (int y = 0; y < image.Height; y++)
|
||||||
{
|
{
|
||||||
for (int x = 0; x < image.Width; x++)
|
for (int x = 0; x < image.Width; x++)
|
||||||
|
@ -899,16 +769,13 @@ public class ScreenMatch
|
||||||
Color pixelColor = image.GetPixel(x, y);
|
Color pixelColor = image.GetPixel(x, y);
|
||||||
byte grayValue = (byte)((pixelColor.R + pixelColor.G + pixelColor.B) / 3);
|
byte grayValue = (byte)((pixelColor.R + pixelColor.G + pixelColor.B) / 3);
|
||||||
|
|
||||||
// Convert the grayscale value to the quantize value
|
// Apply threshold to convert to binary
|
||||||
byte quantizedValue = (byte)((grayValue / step) * step);
|
Color binaryColor = grayValue >= threshold ? Color.White : Color.Black;
|
||||||
|
binaryImage.SetPixel(x, y, binaryColor);
|
||||||
// Renew the colors
|
|
||||||
Color quantizedColor = Color.FromArgb(quantizedValue, quantizedValue, quantizedValue);
|
|
||||||
quantizedImage.SetPixel(x, y, quantizedColor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return quantizedImage;
|
return binaryImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
private uint ComputeBitmapCrc32(Bitmap bitmap)
|
private uint ComputeBitmapCrc32(Bitmap bitmap)
|
||||||
|
|
|
@ -34,20 +34,19 @@ using System.Collections.Generic;
|
||||||
using WelsonJS.TinyINIController;
|
using WelsonJS.TinyINIController;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
|
|
||||||
namespace WelsonJS.Service
|
namespace WelsonJS.Service
|
||||||
{
|
{
|
||||||
public partial class ServiceMain : ServiceBase
|
public partial class ServiceMain : ServiceBase
|
||||||
{
|
{
|
||||||
private readonly static string applicationName = "WelsonJS";
|
|
||||||
private static List<Timer> timers;
|
private static List<Timer> timers;
|
||||||
private ILogger logger;
|
|
||||||
private string workingDirectory;
|
private string workingDirectory;
|
||||||
private string scriptName;
|
private string scriptName;
|
||||||
private string scriptFilePath;
|
private string scriptFilePath;
|
||||||
private string scriptText;
|
private string scriptText;
|
||||||
private ScriptControl scriptControl;
|
private ScriptControl scriptControl;
|
||||||
|
private readonly string logFilePath = Path.Combine(Path.GetTempPath(), "WelsonJS.Service.Log.txt");
|
||||||
|
private readonly string appName = "WelsonJS";
|
||||||
private string[] args;
|
private string[] args;
|
||||||
private bool disabledHeartbeat = false;
|
private bool disabledHeartbeat = false;
|
||||||
private bool disabledScreenTime = false;
|
private bool disabledScreenTime = false;
|
||||||
|
@ -55,20 +54,18 @@ namespace WelsonJS.Service
|
||||||
private ScreenMatch screenMatcher;
|
private ScreenMatch screenMatcher;
|
||||||
private FileEventMonitor fileEventMonitor;
|
private FileEventMonitor fileEventMonitor;
|
||||||
private IniFile settingsFileHandler;
|
private IniFile settingsFileHandler;
|
||||||
private UserVariables userVariablesHandler;
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
private static extern int GetSystemMetrics(int nIndex);
|
private static extern int GetSystemMetrics(int nIndex);
|
||||||
|
|
||||||
private static int SM_REMOTESESSION = 0x1000;
|
private static int SM_REMOTESESSION = 0x1000;
|
||||||
|
|
||||||
public ServiceMain(string[] _args, ILogger _logger)
|
public ServiceMain(string[] args)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
// set arguments and logger
|
// set service arguments
|
||||||
args = _args;
|
this.args = args;
|
||||||
logger = _logger;
|
|
||||||
|
|
||||||
// mapping arguments to each variables
|
// mapping arguments to each variables
|
||||||
var arguments = ParseArguments(this.args);
|
var arguments = ParseArguments(this.args);
|
||||||
|
@ -98,23 +95,19 @@ namespace WelsonJS.Service
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// load the user variables
|
|
||||||
userVariablesHandler = new UserVariables(this);
|
|
||||||
userVariablesHandler.Load();
|
|
||||||
|
|
||||||
// set timers
|
// set timers
|
||||||
timers = new List<Timer>();
|
timers = new List<Timer>();
|
||||||
|
|
||||||
// set working directory
|
// set working directory
|
||||||
if (string.IsNullOrEmpty(workingDirectory))
|
if (string.IsNullOrEmpty(workingDirectory))
|
||||||
{
|
{
|
||||||
workingDirectory = Path.Combine(Path.GetTempPath(), applicationName);
|
workingDirectory = Path.Combine(Path.GetTempPath(), appName);
|
||||||
logger.LogInformation("Working directory not provided. Using default value: " + workingDirectory);
|
Log("Working directory not provided. Using default value: " + workingDirectory);
|
||||||
|
|
||||||
if (!Directory.Exists(workingDirectory))
|
if (!Directory.Exists(workingDirectory))
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(workingDirectory);
|
Directory.CreateDirectory(workingDirectory);
|
||||||
logger.LogInformation("Directory created: " + workingDirectory);
|
Log("Directory created: " + workingDirectory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Directory.SetCurrentDirectory(workingDirectory);
|
Directory.SetCurrentDirectory(workingDirectory);
|
||||||
|
@ -127,14 +120,14 @@ namespace WelsonJS.Service
|
||||||
{
|
{
|
||||||
settingsFileHandler = new IniFile(settingsFilePath);
|
settingsFileHandler = new IniFile(settingsFilePath);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
logger.LogWarning(ex.Message);
|
settingsFileHandler = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.LogInformation($"Configuration file not found: {settingsFilePath}");
|
Log($"Configuration file not found: {settingsFilePath}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// read configrations from settings.ini
|
// read configrations from settings.ini
|
||||||
|
@ -150,7 +143,7 @@ namespace WelsonJS.Service
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if ("true" == ReadSettingsValue(configName))
|
if ("true" == GetSettingsFileHandler().Read(configName, "Service"))
|
||||||
{
|
{
|
||||||
switch (configName)
|
switch (configName)
|
||||||
{
|
{
|
||||||
|
@ -173,7 +166,7 @@ namespace WelsonJS.Service
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogInformation($"{configName} is ignored: {ex.Message}");
|
Log($"{configName} is ignored: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,7 +175,7 @@ namespace WelsonJS.Service
|
||||||
if (string.IsNullOrEmpty(scriptName))
|
if (string.IsNullOrEmpty(scriptName))
|
||||||
{
|
{
|
||||||
scriptName = "defaultService";
|
scriptName = "defaultService";
|
||||||
logger.LogInformation($"Script name not provided. Using default value: {scriptName}");
|
Log($"Script name not provided. Using default value: {scriptName}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// set path of the script
|
// set path of the script
|
||||||
|
@ -191,7 +184,7 @@ namespace WelsonJS.Service
|
||||||
// start the heartbeat
|
// start the heartbeat
|
||||||
if (!disabledHeartbeat)
|
if (!disabledHeartbeat)
|
||||||
{
|
{
|
||||||
HeartbeatClient heartbeatClient = new HeartbeatClient(this, logger);
|
HeartbeatClient heartbeatClient = new HeartbeatClient(this);
|
||||||
Task.Run(heartbeatClient.StartHeartbeatAsync);
|
Task.Run(heartbeatClient.StartHeartbeatAsync);
|
||||||
Task.Run(heartbeatClient.StartEventListenerAsync);
|
Task.Run(heartbeatClient.StartEventListenerAsync);
|
||||||
}
|
}
|
||||||
|
@ -206,32 +199,21 @@ namespace WelsonJS.Service
|
||||||
|
|
||||||
// check this session is the user interactive mode
|
// check this session is the user interactive mode
|
||||||
if (Environment.UserInteractive) {
|
if (Environment.UserInteractive) {
|
||||||
OnUserInteractiveEnvironment();
|
this.OnUserInteractiveEnvironment();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.LogInformation("Disabled the User Interactive Mode. (e.g., OnScreenTime)");
|
Log("Disabled the User Interactive Mode. (e.g., OnScreenTime)");
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation(applicationName + " Service Loaded");
|
// set the log file path
|
||||||
|
logFilePath = Path.Combine(Path.GetTempPath(), "WelsonJS.Service.Log.txt");
|
||||||
|
Log(appName + " Service Loaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ReadSettingsValue(string key, string defaultValue = null)
|
public IniFile GetSettingsFileHandler()
|
||||||
{
|
{
|
||||||
if (settingsFileHandler != null)
|
return settingsFileHandler;
|
||||||
{
|
|
||||||
return settingsFileHandler.Read(key, "Service") ?? defaultValue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logger.LogWarning("Unable to read the value. It seems that settings.ini is not configured correctly.");
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserVariables GetUserVariablesHandler()
|
|
||||||
{
|
|
||||||
return userVariablesHandler;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void TestStartupAndStop()
|
internal void TestStartupAndStop()
|
||||||
|
@ -248,7 +230,7 @@ namespace WelsonJS.Service
|
||||||
// Check exists the entry script file
|
// Check exists the entry script file
|
||||||
if (File.Exists(scriptFilePath))
|
if (File.Exists(scriptFilePath))
|
||||||
{
|
{
|
||||||
logger.LogInformation($"Script file found: {scriptFilePath}");
|
Log($"Script file found: {scriptFilePath}");
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -264,59 +246,47 @@ namespace WelsonJS.Service
|
||||||
|
|
||||||
// make the start arguments
|
// make the start arguments
|
||||||
string[] startArguments;
|
string[] startArguments;
|
||||||
string[] _args;
|
|
||||||
if (Environment.UserInteractive)
|
if (Environment.UserInteractive)
|
||||||
{
|
{
|
||||||
_args = new string[]
|
startArguments = new string[args.Length + 1];
|
||||||
{
|
args.CopyTo(startArguments, 0);
|
||||||
$"--env-file={userVariablesHandler.GetEnvFilePath()}",
|
startArguments[args.Length] = "--user-interactive";
|
||||||
"--user-interactive"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_args = new string[]
|
startArguments = args;
|
||||||
{
|
|
||||||
$"--env-file={userVariablesHandler.GetEnvFilePath()}"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
startArguments = new string[args.Length + _args.Length];
|
|
||||||
args.CopyTo(startArguments, 0);
|
|
||||||
for (int i = 0; i < _args.Length; i++)
|
|
||||||
{
|
|
||||||
startArguments[args.Length + i] = _args[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize
|
// initialize
|
||||||
logger.LogInformation(DispatchServiceEvent("start", startArguments));
|
Log(DispatchServiceEvent("start", startArguments));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogInformation($"Failed to start because of {ex.Message}");
|
Log($"Failed to start because of {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.LogInformation($"Script file not found: {scriptFilePath}");
|
Log($"Script file not found: {scriptFilePath}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trace a Sysmon file events (If Sysinternals Sysmon installed)
|
// Trace a Sysmon file events (If Sysinternals Sysmon installed)
|
||||||
if (!disabledFileMonitor)
|
if (!disabledFileMonitor)
|
||||||
{
|
{
|
||||||
fileEventMonitor = new FileEventMonitor(this, workingDirectory, logger);
|
fileEventMonitor = new FileEventMonitor(this, workingDirectory);
|
||||||
fileEventMonitor.Start();
|
fileEventMonitor.Start();
|
||||||
|
|
||||||
logger.LogInformation("File Event Monitor Started");
|
Log("File Event Monitor Started");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.LogInformation("File Event Monitor is Disabled");
|
Log("File Event Monitor is Disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start all the registered timers
|
// Start all the registered timers
|
||||||
timers.ForEach(timer => timer?.Start());
|
timers.ForEach(timer => timer?.Start());
|
||||||
|
|
||||||
logger.LogInformation(applicationName + " Service Started");
|
Log(appName + " Service Started");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnStop()
|
protected override void OnStop()
|
||||||
|
@ -330,16 +300,16 @@ namespace WelsonJS.Service
|
||||||
// dispatch stop callback
|
// dispatch stop callback
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
logger.LogInformation(DispatchServiceEvent("stop"));
|
Log(DispatchServiceEvent("stop"));
|
||||||
scriptControl?.Reset();
|
scriptControl?.Reset();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogInformation("Exception when stop: " + ex.Message);
|
Log("Exception when stop: " + ex.Message);
|
||||||
}
|
}
|
||||||
scriptControl = null;
|
scriptControl = null;
|
||||||
|
|
||||||
logger.LogInformation(applicationName + " Service Stopped");
|
Log(appName + " Service Stopped");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnUserInteractiveEnvironment()
|
private void OnUserInteractiveEnvironment()
|
||||||
|
@ -348,13 +318,13 @@ namespace WelsonJS.Service
|
||||||
if (GetSystemMetrics(SM_REMOTESESSION) > 0)
|
if (GetSystemMetrics(SM_REMOTESESSION) > 0)
|
||||||
{
|
{
|
||||||
disabledScreenTime = true;
|
disabledScreenTime = true;
|
||||||
logger.LogInformation("This application may not work correctly in a remote desktop session");
|
Log("This application may not work correctly in a remote desktop session");
|
||||||
}
|
}
|
||||||
|
|
||||||
// set screen timer
|
// set screen timer
|
||||||
if (!disabledScreenTime)
|
if (!disabledScreenTime)
|
||||||
{
|
{
|
||||||
screenMatcher = new ScreenMatch(this, workingDirectory, logger);
|
screenMatcher = new ScreenMatch(this, workingDirectory);
|
||||||
|
|
||||||
Timer screenTimer = new Timer
|
Timer screenTimer = new Timer
|
||||||
{
|
{
|
||||||
|
@ -363,13 +333,13 @@ namespace WelsonJS.Service
|
||||||
screenTimer.Elapsed += OnScreenTime;
|
screenTimer.Elapsed += OnScreenTime;
|
||||||
timers.Add(screenTimer);
|
timers.Add(screenTimer);
|
||||||
|
|
||||||
logger.LogInformation("Screen Time Event Enabled");
|
Log("Screen Time Event Enabled");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
disabledScreenTime = true;
|
disabledScreenTime = true;
|
||||||
|
|
||||||
logger.LogInformation("Screen Time Event Disabled");
|
Log("Screen Time Event Disabled");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,11 +347,11 @@ namespace WelsonJS.Service
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
logger.LogInformation(DispatchServiceEvent("elapsedTime"));
|
Log(DispatchServiceEvent("elapsedTime"));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogInformation("Exception when elapsed time: " + ex.Message);
|
Log("Exception when elapsed time: " + ex.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,7 +362,7 @@ namespace WelsonJS.Service
|
||||||
List<ScreenMatchResult> matchedResults = screenMatcher.CaptureAndMatch();
|
List<ScreenMatchResult> matchedResults = screenMatcher.CaptureAndMatch();
|
||||||
matchedResults.ForEach(result =>
|
matchedResults.ForEach(result =>
|
||||||
{
|
{
|
||||||
logger.LogInformation(DispatchServiceEvent("screenTemplateMatched", new string[]
|
Log(DispatchServiceEvent("screenTemplateMatched", new string[]
|
||||||
{
|
{
|
||||||
result.FileName,
|
result.FileName,
|
||||||
result.ScreenNumber.ToString(),
|
result.ScreenNumber.ToString(),
|
||||||
|
@ -403,7 +373,7 @@ namespace WelsonJS.Service
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogInformation($"Waiting a next screen time... {ex.Message}");
|
Log($"Waiting a next screen time... {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,7 +393,7 @@ namespace WelsonJS.Service
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.LogInformation("InvokeScriptMethod Ignored: " + methodName);
|
Log("InvokeScriptMethod Ignored: " + methodName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return "void";
|
return "void";
|
||||||
|
@ -441,7 +411,7 @@ namespace WelsonJS.Service
|
||||||
if (index > 2)
|
if (index > 2)
|
||||||
{
|
{
|
||||||
var key = arg.Substring(2, index - 2);
|
var key = arg.Substring(2, index - 2);
|
||||||
var value = arg.Substring(index + 1).Trim('"');
|
var value = arg.Substring(index + 1);
|
||||||
arguments[key] = value;
|
arguments[key] = value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -455,29 +425,20 @@ namespace WelsonJS.Service
|
||||||
return arguments;
|
return arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScreenMatch.TemplateInfo GetNextTemplateInfo()
|
public string GetNextTemplateName()
|
||||||
{
|
{
|
||||||
string templateName = string.Empty;
|
string templateName = string.Empty;
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
templateName = DispatchServiceEvent("screenNextTemplate");
|
templateName = DispatchServiceEvent("screenNextTemplate");
|
||||||
|
|
||||||
// Check if the received value contains an index
|
|
||||||
string[] parts = templateName.Split(':');
|
|
||||||
if (parts.Length > 1)
|
|
||||||
{
|
|
||||||
templateName = parts[0];
|
|
||||||
int.TryParse(parts[1], out index);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
logger.LogInformation($"Use all templates because of {ex.Message}");
|
Log($"Use all templates because of {ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ScreenMatch.TemplateInfo(templateName, index);
|
return templateName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string DispatchServiceEvent(string eventType, string[] args = null)
|
public string DispatchServiceEvent(string eventType, string[] args = null)
|
||||||
|
@ -492,5 +453,27 @@ namespace WelsonJS.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Log(string message)
|
||||||
|
{
|
||||||
|
string _message = $"{DateTime.Now}: {message}";
|
||||||
|
|
||||||
|
if (Environment.UserInteractive)
|
||||||
|
{
|
||||||
|
Console.WriteLine(_message);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (StreamWriter writer = new StreamWriter(logFilePath, true))
|
||||||
|
{
|
||||||
|
writer.WriteLine(_message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Failed to write log: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,82 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.ServiceProcess;
|
|
||||||
|
|
||||||
namespace WelsonJS.Service
|
|
||||||
{
|
|
||||||
public class UserVariables
|
|
||||||
{
|
|
||||||
private ServiceMain parent;
|
|
||||||
private Dictionary<string, string> userVariables;
|
|
||||||
private string envFilePath;
|
|
||||||
|
|
||||||
public UserVariables(ServiceBase parent)
|
|
||||||
{
|
|
||||||
envFilePath = Path.Combine(Program.GetAppDataPath(), "welsonjs_default.env");
|
|
||||||
this.parent = (ServiceMain)parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load user-defined variables from the temporary folder in .env format
|
|
||||||
public void Load()
|
|
||||||
{
|
|
||||||
if (File.Exists(envFilePath))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
string fileContent = File.ReadAllText(envFilePath);
|
|
||||||
// Split based on new line characters
|
|
||||||
string[] keyValuePairs = fileContent.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
|
|
||||||
|
|
||||||
userVariables = new Dictionary<string, string>();
|
|
||||||
|
|
||||||
foreach (string pair in keyValuePairs)
|
|
||||||
{
|
|
||||||
// Split by the first occurrence of '='
|
|
||||||
int indexOfEquals = pair.IndexOf('=');
|
|
||||||
if (indexOfEquals != -1)
|
|
||||||
{
|
|
||||||
string key = pair.Substring(0, indexOfEquals).Trim();
|
|
||||||
string value = pair.Substring(indexOfEquals + 1).Trim();
|
|
||||||
|
|
||||||
// Remove surrounding quotes if present
|
|
||||||
if (value.StartsWith("\"") && value.EndsWith("\""))
|
|
||||||
{
|
|
||||||
value = value.Substring(1, value.Length - 2); // Remove the first and last character
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unescape double quotes in the value
|
|
||||||
value = value.Replace("\\\"", "\"");
|
|
||||||
|
|
||||||
userVariables[key] = value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception($"Error parsing line: '{pair}'.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Error loading variable file: {ex.Message}");
|
|
||||||
userVariables = new Dictionary<string, string>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
userVariables = new Dictionary<string, string>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetValue(string name)
|
|
||||||
{
|
|
||||||
userVariables.TryGetValue(name, out string value);
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetEnvFilePath()
|
|
||||||
{
|
|
||||||
return envFilePath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<Import Project="..\packages\Grpc.Tools.2.67.0\build\Grpc.Tools.props" Condition="Exists('..\packages\Grpc.Tools.2.67.0\build\Grpc.Tools.props')" />
|
<Import Project="..\packages\Grpc.Tools.2.66.0\build\Grpc.Tools.props" Condition="Exists('..\packages\Grpc.Tools.2.66.0\build\Grpc.Tools.props')" />
|
||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
@ -103,72 +103,42 @@
|
||||||
<Reference Include="ClamAV.Net, Version=0.1.166.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="ClamAV.Net, Version=0.1.166.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\ClamAV.Net.0.1.166\lib\netstandard2.0\ClamAV.Net.dll</HintPath>
|
<HintPath>..\packages\ClamAV.Net.0.1.166\lib\netstandard2.0\ClamAV.Net.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Google.Protobuf, Version=3.28.2.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
|
<Reference Include="Google.Protobuf, Version=3.28.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Google.Protobuf.3.28.2\lib\net45\Google.Protobuf.dll</HintPath>
|
<HintPath>..\packages\Google.Protobuf.3.28.0\lib\net45\Google.Protobuf.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Grpc.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
|
<Reference Include="Grpc.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Grpc.Core.2.46.6\lib\net45\Grpc.Core.dll</HintPath>
|
<HintPath>..\packages\Grpc.Core.2.46.6\lib\net45\Grpc.Core.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Grpc.Core.Api, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
|
<Reference Include="Grpc.Core.Api, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Grpc.Core.Api.2.66.0\lib\net462\Grpc.Core.Api.dll</HintPath>
|
<HintPath>..\packages\Grpc.Core.Api.2.65.0\lib\net462\Grpc.Core.Api.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Grpc.Net.Client, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
|
<Reference Include="Grpc.Net.Client, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Grpc.Net.Client.2.66.0\lib\net462\Grpc.Net.Client.dll</HintPath>
|
<HintPath>..\packages\Grpc.Net.Client.2.65.0\lib\net462\Grpc.Net.Client.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Grpc.Net.Client.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
|
<Reference Include="Grpc.Net.Client.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Grpc.Net.Client.Web.2.66.0\lib\netstandard2.0\Grpc.Net.Client.Web.dll</HintPath>
|
<HintPath>..\packages\Grpc.Net.Client.Web.2.65.0\lib\netstandard2.0\Grpc.Net.Client.Web.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Grpc.Net.Common, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
|
<Reference Include="Grpc.Net.Common, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Grpc.Net.Common.2.66.0\lib\netstandard2.0\Grpc.Net.Common.dll</HintPath>
|
<HintPath>..\packages\Grpc.Net.Common.2.65.0\lib\netstandard2.0\Grpc.Net.Common.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.8.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
|
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.8.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
<Reference Include="Microsoft.Extensions.Configuration, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=8.0.0.1, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Microsoft.Extensions.Configuration.8.0.0\lib\net462\Microsoft.Extensions.Configuration.dll</HintPath>
|
<HintPath>..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.8.0.1\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Microsoft.Extensions.Configuration.Abstractions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=8.0.0.1, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Microsoft.Extensions.Configuration.Abstractions.8.0.0\lib\net462\Microsoft.Extensions.Configuration.Abstractions.dll</HintPath>
|
<HintPath>..\packages\Microsoft.Extensions.Logging.Abstractions.8.0.1\lib\net462\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Microsoft.Extensions.Configuration.Binder, Version=8.0.0.2, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
<Reference Include="RestSharp, Version=112.0.0.0, Culture=neutral, PublicKeyToken=598062e77f915f75">
|
||||||
<HintPath>..\packages\Microsoft.Extensions.Configuration.Binder.8.0.2\lib\net462\Microsoft.Extensions.Configuration.Binder.dll</HintPath>
|
<HintPath>..\packages\RestSharp.112.0.0\lib\net48\RestSharp.dll</HintPath>
|
||||||
</Reference>
|
<Private>True</Private>
|
||||||
<Reference Include="Microsoft.Extensions.DependencyInjection, Version=8.0.0.1, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\packages\Microsoft.Extensions.DependencyInjection.8.0.1\lib\net462\Microsoft.Extensions.DependencyInjection.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=8.0.0.2, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.8.0.2\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Microsoft.Extensions.Logging, Version=8.0.0.1, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\packages\Microsoft.Extensions.Logging.8.0.1\lib\net462\Microsoft.Extensions.Logging.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=8.0.0.2, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\packages\Microsoft.Extensions.Logging.Abstractions.8.0.2\lib\net462\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Microsoft.Extensions.Logging.Configuration, Version=8.0.0.1, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\packages\Microsoft.Extensions.Logging.Configuration.8.0.1\lib\net462\Microsoft.Extensions.Logging.Configuration.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Microsoft.Extensions.Logging.Console, Version=8.0.0.1, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\packages\Microsoft.Extensions.Logging.Console.8.0.1\lib\net462\Microsoft.Extensions.Logging.Console.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Microsoft.Extensions.Options, Version=8.0.0.2, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\packages\Microsoft.Extensions.Options.8.0.2\lib\net462\Microsoft.Extensions.Options.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Microsoft.Extensions.Options.ConfigurationExtensions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\packages\Microsoft.Extensions.Options.ConfigurationExtensions.8.0.0\lib\net462\Microsoft.Extensions.Options.ConfigurationExtensions.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="Microsoft.Extensions.Primitives, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\packages\Microsoft.Extensions.Primitives.8.0.0\lib\net462\Microsoft.Extensions.Primitives.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="RestSharp, Version=112.1.0.0, Culture=neutral, PublicKeyToken=598062e77f915f75, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\packages\RestSharp.112.1.0\lib\net48\RestSharp.dll</HintPath>
|
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
<Reference Include="System.Buffers, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
|
<HintPath>..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.ComponentModel.DataAnnotations" />
|
|
||||||
<Reference Include="System.Configuration.Install" />
|
<Reference Include="System.Configuration.Install" />
|
||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
<Reference Include="System.Diagnostics.DiagnosticSource, Version=8.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
<Reference Include="System.Diagnostics.DiagnosticSource, Version=8.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||||
|
@ -190,7 +160,6 @@
|
||||||
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
|
<HintPath>..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Runtime" />
|
|
||||||
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
|
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
@ -198,8 +167,8 @@
|
||||||
<Reference Include="System.Text.Encodings.Web, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
<Reference Include="System.Text.Encodings.Web, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\System.Text.Encodings.Web.8.0.0\lib\net462\System.Text.Encodings.Web.dll</HintPath>
|
<HintPath>..\packages\System.Text.Encodings.Web.8.0.0\lib\net462\System.Text.Encodings.Web.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Text.Json, Version=8.0.0.5, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
<Reference Include="System.Text.Json, Version=8.0.0.4, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\System.Text.Json.8.0.5\lib\net462\System.Text.Json.dll</HintPath>
|
<HintPath>..\packages\System.Text.Json.8.0.4\lib\net462\System.Text.Json.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll</HintPath>
|
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll</HintPath>
|
||||||
|
@ -217,9 +186,6 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="FileEventMonitor.cs" />
|
<Compile Include="FileEventMonitor.cs" />
|
||||||
<Compile Include="HeartbeatClient.cs" />
|
<Compile Include="HeartbeatClient.cs" />
|
||||||
<Compile Include="Logging\FileLogger.cs" />
|
|
||||||
<Compile Include="Logging\FileLoggerExtensions.cs" />
|
|
||||||
<Compile Include="Logging\FileLoggerProvider.cs" />
|
|
||||||
<Compile Include="Model\FileMatchResult.cs" />
|
<Compile Include="Model\FileMatchResult.cs" />
|
||||||
<Compile Include="ServiceMain.cs">
|
<Compile Include="ServiceMain.cs">
|
||||||
<SubType>Component</SubType>
|
<SubType>Component</SubType>
|
||||||
|
@ -237,7 +203,6 @@
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="ScreenMatch.cs" />
|
<Compile Include="ScreenMatch.cs" />
|
||||||
<Compile Include="Model\ScreenMatchResult.cs" />
|
<Compile Include="Model\ScreenMatchResult.cs" />
|
||||||
<Compile Include="UserVariables.cs" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<COMReference Include="MSScriptControl">
|
<COMReference Include="MSScriptControl">
|
||||||
|
@ -290,11 +255,11 @@
|
||||||
<ErrorText>이 프로젝트는 이 컴퓨터에 없는 NuGet 패키지를 참조합니다. 해당 패키지를 다운로드하려면 NuGet 패키지 복원을 사용하십시오. 자세한 내용은 http://go.microsoft.com/fwlink/?LinkID=322105를 참조하십시오. 누락된 파일은 {0}입니다.</ErrorText>
|
<ErrorText>이 프로젝트는 이 컴퓨터에 없는 NuGet 패키지를 참조합니다. 해당 패키지를 다운로드하려면 NuGet 패키지 복원을 사용하십시오. 자세한 내용은 http://go.microsoft.com/fwlink/?LinkID=322105를 참조하십시오. 누락된 파일은 {0}입니다.</ErrorText>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Error Condition="!Exists('..\packages\Grpc.Core.2.46.6\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.2.46.6\build\net45\Grpc.Core.targets'))" />
|
<Error Condition="!Exists('..\packages\Grpc.Core.2.46.6\build\net45\Grpc.Core.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Core.2.46.6\build\net45\Grpc.Core.targets'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Grpc.Tools.2.66.0\build\Grpc.Tools.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Tools.2.66.0\build\Grpc.Tools.props'))" />
|
||||||
|
<Error Condition="!Exists('..\packages\Grpc.Tools.2.66.0\build\Grpc.Tools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Tools.2.66.0\build\Grpc.Tools.targets'))" />
|
||||||
<Error Condition="!Exists('..\packages\Tesseract.5.2.0\build\Tesseract.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Tesseract.5.2.0\build\Tesseract.targets'))" />
|
<Error Condition="!Exists('..\packages\Tesseract.5.2.0\build\Tesseract.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Tesseract.5.2.0\build\Tesseract.targets'))" />
|
||||||
<Error Condition="!Exists('..\packages\Grpc.Tools.2.67.0\build\Grpc.Tools.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Tools.2.67.0\build\Grpc.Tools.props'))" />
|
|
||||||
<Error Condition="!Exists('..\packages\Grpc.Tools.2.67.0\build\Grpc.Tools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Grpc.Tools.2.67.0\build\Grpc.Tools.targets'))" />
|
|
||||||
</Target>
|
</Target>
|
||||||
<Import Project="..\packages\Grpc.Core.2.46.6\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.2.46.6\build\net45\Grpc.Core.targets')" />
|
<Import Project="..\packages\Grpc.Core.2.46.6\build\net45\Grpc.Core.targets" Condition="Exists('..\packages\Grpc.Core.2.46.6\build\net45\Grpc.Core.targets')" />
|
||||||
|
<Import Project="..\packages\Grpc.Tools.2.66.0\build\Grpc.Tools.targets" Condition="Exists('..\packages\Grpc.Tools.2.66.0\build\Grpc.Tools.targets')" />
|
||||||
<Import Project="..\packages\Tesseract.5.2.0\build\Tesseract.targets" Condition="Exists('..\packages\Tesseract.5.2.0\build\Tesseract.targets')" />
|
<Import Project="..\packages\Tesseract.5.2.0\build\Tesseract.targets" Condition="Exists('..\packages\Tesseract.5.2.0\build\Tesseract.targets')" />
|
||||||
<Import Project="..\packages\Grpc.Tools.2.67.0\build\Grpc.Tools.targets" Condition="Exists('..\packages\Grpc.Tools.2.67.0\build\Grpc.Tools.targets')" />
|
|
||||||
</Project>
|
</Project>
|
|
@ -21,7 +21,7 @@
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
<dependentAssembly>
|
<dependentAssembly>
|
||||||
<assemblyIdentity name="Microsoft.Extensions.Logging.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
|
<assemblyIdentity name="Microsoft.Extensions.Logging.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
|
||||||
<bindingRedirect oldVersion="0.0.0.0-8.0.0.2" newVersion="8.0.0.2" />
|
<bindingRedirect oldVersion="0.0.0.0-8.0.0.1" newVersion="8.0.0.1" />
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
<dependentAssembly>
|
<dependentAssembly>
|
||||||
<assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
<assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||||
|
@ -65,7 +65,7 @@
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
<dependentAssembly>
|
<dependentAssembly>
|
||||||
<assemblyIdentity name="Microsoft.Extensions.DependencyInjection.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
|
<assemblyIdentity name="Microsoft.Extensions.DependencyInjection.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
|
||||||
<bindingRedirect oldVersion="0.0.0.0-8.0.0.2" newVersion="8.0.0.2" />
|
<bindingRedirect oldVersion="0.0.0.0-8.0.0.1" newVersion="8.0.0.1" />
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
<dependentAssembly>
|
<dependentAssembly>
|
||||||
<assemblyIdentity name="RestSharp" publicKeyToken="598062e77f915f75" culture="neutral" />
|
<assemblyIdentity name="RestSharp" publicKeyToken="598062e77f915f75" culture="neutral" />
|
||||||
|
@ -81,20 +81,12 @@
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
<dependentAssembly>
|
<dependentAssembly>
|
||||||
<assemblyIdentity name="System.Text.Json" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
<assemblyIdentity name="System.Text.Json" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||||
<bindingRedirect oldVersion="0.0.0.0-8.0.0.5" newVersion="8.0.0.5" />
|
<bindingRedirect oldVersion="0.0.0.0-8.0.0.4" newVersion="8.0.0.4" />
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
<dependentAssembly>
|
<dependentAssembly>
|
||||||
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
|
||||||
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
|
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
<dependentAssembly>
|
|
||||||
<assemblyIdentity name="Microsoft.Extensions.Options" publicKeyToken="adb9793829ddae60" culture="neutral" />
|
|
||||||
<bindingRedirect oldVersion="0.0.0.0-8.0.0.2" newVersion="8.0.0.2" />
|
|
||||||
</dependentAssembly>
|
|
||||||
<dependentAssembly>
|
|
||||||
<assemblyIdentity name="Microsoft.Extensions.Configuration.Binder" publicKeyToken="adb9793829ddae60" culture="neutral" />
|
|
||||||
<bindingRedirect oldVersion="0.0.0.0-8.0.0.2" newVersion="8.0.0.2" />
|
|
||||||
</dependentAssembly>
|
|
||||||
</assemblyBinding>
|
</assemblyBinding>
|
||||||
</runtime>
|
</runtime>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -1,28 +1,18 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<packages>
|
||||||
<package id="ClamAV.Net" version="0.1.166" targetFramework="net48" />
|
<package id="ClamAV.Net" version="0.1.166" targetFramework="net48" />
|
||||||
<package id="Google.Protobuf" version="3.28.2" targetFramework="net48" />
|
<package id="Google.Protobuf" version="3.28.0" targetFramework="net48" />
|
||||||
<package id="Grpc" version="2.46.6" targetFramework="net48" />
|
<package id="Grpc" version="2.46.6" targetFramework="net48" />
|
||||||
<package id="Grpc.Core" version="2.46.6" targetFramework="net48" />
|
<package id="Grpc.Core" version="2.46.6" targetFramework="net48" />
|
||||||
<package id="Grpc.Core.Api" version="2.66.0" targetFramework="net48" />
|
<package id="Grpc.Core.Api" version="2.65.0" targetFramework="net48" />
|
||||||
<package id="Grpc.Net.Client" version="2.66.0" targetFramework="net48" />
|
<package id="Grpc.Net.Client" version="2.65.0" targetFramework="net48" />
|
||||||
<package id="Grpc.Net.Client.Web" version="2.66.0" targetFramework="net48" />
|
<package id="Grpc.Net.Client.Web" version="2.65.0" targetFramework="net48" />
|
||||||
<package id="Grpc.Net.Common" version="2.66.0" targetFramework="net48" />
|
<package id="Grpc.Net.Common" version="2.65.0" targetFramework="net48" />
|
||||||
<package id="Grpc.Tools" version="2.67.0" targetFramework="net48" developmentDependency="true" />
|
<package id="Grpc.Tools" version="2.66.0" targetFramework="net48" developmentDependency="true" />
|
||||||
<package id="Microsoft.Bcl.AsyncInterfaces" version="8.0.0" targetFramework="net48" />
|
<package id="Microsoft.Bcl.AsyncInterfaces" version="8.0.0" targetFramework="net48" />
|
||||||
<package id="Microsoft.Extensions.Configuration" version="8.0.0" targetFramework="net48" />
|
<package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="8.0.1" targetFramework="net48" />
|
||||||
<package id="Microsoft.Extensions.Configuration.Abstractions" version="8.0.0" targetFramework="net48" />
|
<package id="Microsoft.Extensions.Logging.Abstractions" version="8.0.1" targetFramework="net48" />
|
||||||
<package id="Microsoft.Extensions.Configuration.Binder" version="8.0.2" targetFramework="net48" />
|
<package id="RestSharp" version="112.0.0" targetFramework="net48" />
|
||||||
<package id="Microsoft.Extensions.DependencyInjection" version="8.0.1" targetFramework="net48" />
|
|
||||||
<package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="8.0.2" targetFramework="net48" />
|
|
||||||
<package id="Microsoft.Extensions.Logging" version="8.0.1" targetFramework="net48" />
|
|
||||||
<package id="Microsoft.Extensions.Logging.Abstractions" version="8.0.2" targetFramework="net48" />
|
|
||||||
<package id="Microsoft.Extensions.Logging.Configuration" version="8.0.1" targetFramework="net48" />
|
|
||||||
<package id="Microsoft.Extensions.Logging.Console" version="8.0.1" targetFramework="net48" />
|
|
||||||
<package id="Microsoft.Extensions.Options" version="8.0.2" targetFramework="net48" />
|
|
||||||
<package id="Microsoft.Extensions.Options.ConfigurationExtensions" version="8.0.0" targetFramework="net48" />
|
|
||||||
<package id="Microsoft.Extensions.Primitives" version="8.0.0" targetFramework="net48" />
|
|
||||||
<package id="RestSharp" version="112.1.0" targetFramework="net48" />
|
|
||||||
<package id="System.Buffers" version="4.5.1" targetFramework="net48" />
|
<package id="System.Buffers" version="4.5.1" targetFramework="net48" />
|
||||||
<package id="System.Diagnostics.DiagnosticSource" version="8.0.1" targetFramework="net48" />
|
<package id="System.Diagnostics.DiagnosticSource" version="8.0.1" targetFramework="net48" />
|
||||||
<package id="System.IO.Hashing" version="8.0.0" targetFramework="net48" />
|
<package id="System.IO.Hashing" version="8.0.0" targetFramework="net48" />
|
||||||
|
@ -31,7 +21,7 @@
|
||||||
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net48" />
|
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net48" />
|
||||||
<package id="System.Runtime.CompilerServices.Unsafe" version="6.0.0" targetFramework="net48" />
|
<package id="System.Runtime.CompilerServices.Unsafe" version="6.0.0" targetFramework="net48" />
|
||||||
<package id="System.Text.Encodings.Web" version="8.0.0" targetFramework="net48" />
|
<package id="System.Text.Encodings.Web" version="8.0.0" targetFramework="net48" />
|
||||||
<package id="System.Text.Json" version="8.0.5" targetFramework="net48" />
|
<package id="System.Text.Json" version="8.0.4" targetFramework="net48" />
|
||||||
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net48" />
|
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net48" />
|
||||||
<package id="System.ValueTuple" version="4.5.0" targetFramework="net48" />
|
<package id="System.ValueTuple" version="4.5.0" targetFramework="net48" />
|
||||||
<package id="Tesseract" version="5.2.0" targetFramework="net48" />
|
<package id="Tesseract" version="5.2.0" targetFramework="net48" />
|
||||||
|
|
|
@ -1,614 +0,0 @@
|
||||||
/*
|
|
||||||
* WelsonJS.Toolkit: WelsonJS native component
|
|
||||||
*
|
|
||||||
* filename:
|
|
||||||
* ARIA.cs
|
|
||||||
*
|
|
||||||
* description:
|
|
||||||
* ARIA(KS X 1213-1, RFC5794, RFC6209) cryptography algorithm implementation (Experimental)
|
|
||||||
*
|
|
||||||
* website:
|
|
||||||
* - https://github.com/gnh1201/welsonjs
|
|
||||||
* - https://catswords.social/@catswords_oss
|
|
||||||
* - https://teams.live.com/l/community/FEACHncAhq8ldnojAI
|
|
||||||
* - https://discord.gg/XKG5CjtXEj
|
|
||||||
*
|
|
||||||
* authors:
|
|
||||||
* - Namhyeon Go (@gnh1201) <abuse@catswords.net>
|
|
||||||
* - @angelkum (blog.naver.com)
|
|
||||||
* - KISA(Korea Internet & Security Agency) (kisa.or.kr)
|
|
||||||
* - National Security Research Institute (NSRI)
|
|
||||||
* - National Intelligence Service (nis.go.kr)
|
|
||||||
*
|
|
||||||
* references:
|
|
||||||
* - https://seed.kisa.or.kr/kisa/Board/19/detailView.do
|
|
||||||
* - https://blog.naver.com/angelkum/130154153446
|
|
||||||
* - https://www.ncsc.go.kr:4018/PageLink.do?link=forward:/PageContent.do&tempParam1=&menuNo=060000&subMenuNo=060200&thirdMenuNo=
|
|
||||||
* - https://www.nis.go.kr/AF/1_7_3_1.do
|
|
||||||
* - https://datatracker.ietf.org/doc/html/rfc5794
|
|
||||||
* - https://datatracker.ietf.org/doc/html/rfc6209
|
|
||||||
* - https://github.com/eGovFrame/egovframework.rte.root/blob/master/Foundation/egovframework.rte.fdl.crypto/src/main/java/egovframework/rte/fdl/cryptography/impl/aria/ARIAEngine.java
|
|
||||||
* - https://ics.catswords.net/ARIA-specification.pdf
|
|
||||||
* - https://ics.catswords.net/ARIA-testvector.pdf
|
|
||||||
*
|
|
||||||
* license:
|
|
||||||
* GPLv3 or MS-RL(Microsoft Reciprocal License)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace WelsonJS.Cryptography
|
|
||||||
{
|
|
||||||
public class ARIA
|
|
||||||
{
|
|
||||||
private static readonly uint[,] KRK = new uint[,] {
|
|
||||||
{0x517cc1b7, 0x27220a94, 0xfe13abe8, 0xfa9a6ee0},
|
|
||||||
{0x6db14acc, 0x9e21c820, 0xff28b1d5, 0xef5de2b0},
|
|
||||||
{0xdb92371d, 0x2126e970, 0x03249775, 0x04e8c90e}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly byte[] S1 = new byte[256];
|
|
||||||
private static readonly byte[] S2 = new byte[256];
|
|
||||||
private static readonly byte[] X1 = new byte[256];
|
|
||||||
private static readonly byte[] X2 = new byte[256];
|
|
||||||
|
|
||||||
private static readonly uint[] TS1 = new uint[256];
|
|
||||||
private static readonly uint[] TS2 = new uint[256];
|
|
||||||
private static readonly uint[] TX1 = new uint[256];
|
|
||||||
private static readonly uint[] TX2 = new uint[256];
|
|
||||||
|
|
||||||
// Static initializer. For setting up the tables
|
|
||||||
static ARIA()
|
|
||||||
{
|
|
||||||
uint[] exp = new uint[256];
|
|
||||||
uint[] log = new uint[256];
|
|
||||||
exp[0] = 1;
|
|
||||||
for (int i = 1; i < 256; i++)
|
|
||||||
{
|
|
||||||
uint j = (exp[i - 1] << 1) ^ exp[i - 1];
|
|
||||||
if ((j & 0x100) != 0) j ^= 0x11b;
|
|
||||||
exp[i] = j;
|
|
||||||
}
|
|
||||||
for (int i = 1; i < 255; i++)
|
|
||||||
log[exp[i]] = (uint)i;
|
|
||||||
|
|
||||||
uint[,] A = new uint[,] {
|
|
||||||
{1, 0, 0, 0, 1, 1, 1, 1},
|
|
||||||
{1, 1, 0, 0, 0, 1, 1, 1},
|
|
||||||
{1, 1, 1, 0, 0, 0, 1, 1},
|
|
||||||
{1, 1, 1, 1, 0, 0, 0, 1},
|
|
||||||
{1, 1, 1, 1, 1, 0, 0, 0},
|
|
||||||
{0, 1, 1, 1, 1, 1, 0, 0},
|
|
||||||
{0, 0, 1, 1, 1, 1, 1, 0},
|
|
||||||
{0, 0, 0, 1, 1, 1, 1, 1}
|
|
||||||
};
|
|
||||||
|
|
||||||
uint[,] B = new uint[,] {
|
|
||||||
{0, 1, 0, 1, 1, 1, 1, 0},
|
|
||||||
{0, 0, 1, 1, 1, 1, 0, 1},
|
|
||||||
{1, 1, 0, 1, 0, 1, 1, 1},
|
|
||||||
{1, 0, 0, 1, 1, 1, 0, 1},
|
|
||||||
{0, 0, 1, 0, 1, 1, 0, 0},
|
|
||||||
{1, 0, 0, 0, 0, 0, 0, 1},
|
|
||||||
{0, 1, 0, 1, 1, 1, 0, 1},
|
|
||||||
{1, 1, 0, 1, 0, 0, 1, 1}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (int i = 0; i < 256; i++)
|
|
||||||
{
|
|
||||||
uint t = 0, p;
|
|
||||||
if (i == 0)
|
|
||||||
p = 0;
|
|
||||||
else
|
|
||||||
p = exp[255 - log[i]];
|
|
||||||
for (int j = 0; j < 8; j++)
|
|
||||||
{
|
|
||||||
uint s = 0;
|
|
||||||
for (int k = 0; k < 8; k++)
|
|
||||||
{
|
|
||||||
if (((p >> (7 - k)) & 0x01) != 0)
|
|
||||||
s ^= A[k, j];
|
|
||||||
}
|
|
||||||
t = (t << 1) ^ s;
|
|
||||||
}
|
|
||||||
t ^= 0x63;
|
|
||||||
S1[i] = (byte)t;
|
|
||||||
X1[t] = (byte)i;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < 256; i++)
|
|
||||||
{
|
|
||||||
uint t = 0, p;
|
|
||||||
if (i == 0)
|
|
||||||
p = 0;
|
|
||||||
else
|
|
||||||
p = exp[(247 * log[i]) % 255];
|
|
||||||
for (int j = 0; j < 8; j++)
|
|
||||||
{
|
|
||||||
uint s = 0;
|
|
||||||
for (int k = 0; k < 8; k++)
|
|
||||||
{
|
|
||||||
if (((p >> k) & 0x01) != 0)
|
|
||||||
s ^= B[7 - j, k];
|
|
||||||
}
|
|
||||||
t = (t << 1) ^ s;
|
|
||||||
}
|
|
||||||
t ^= 0xe2;
|
|
||||||
S2[i] = (byte)t;
|
|
||||||
X2[t] = (byte)i;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 256; i++)
|
|
||||||
{
|
|
||||||
TS1[i] = (uint)0x00010101 * (S1[i] & (uint)0xff);
|
|
||||||
TS2[i] = (uint)0x01000101 * (S2[i] & (uint)0xff);
|
|
||||||
TX1[i] = (uint)0x01010001 * (X1[i] & (uint)0xff);
|
|
||||||
TX2[i] = (uint)0x01010100 * (X2[i] & (uint)0xff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private int keySize = 0;
|
|
||||||
private int numberOfRounds = 0;
|
|
||||||
private byte[] masterKey = null;
|
|
||||||
private uint[] encRoundKeys = null, decRoundKeys = null;
|
|
||||||
|
|
||||||
public ARIA(int keySize)
|
|
||||||
{
|
|
||||||
SetKeySize(keySize);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets the class so that it can be reused for another master key.
|
|
||||||
*/
|
|
||||||
private void Reset()
|
|
||||||
{
|
|
||||||
keySize = 0;
|
|
||||||
numberOfRounds = 0;
|
|
||||||
masterKey = null;
|
|
||||||
encRoundKeys = null;
|
|
||||||
decRoundKeys = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetKeySize()
|
|
||||||
{
|
|
||||||
return keySize;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetKeySize(int _keySize)
|
|
||||||
{
|
|
||||||
Reset();
|
|
||||||
|
|
||||||
if (_keySize != 128 && _keySize != 192 && _keySize != 256)
|
|
||||||
throw new CryptographicException("keySize=" + _keySize);
|
|
||||||
|
|
||||||
switch (_keySize)
|
|
||||||
{
|
|
||||||
case 128:
|
|
||||||
numberOfRounds = 12;
|
|
||||||
break;
|
|
||||||
case 192:
|
|
||||||
numberOfRounds = 14;
|
|
||||||
break;
|
|
||||||
case 256:
|
|
||||||
numberOfRounds = 16;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
keySize = _keySize;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetKey(byte[] masterKey)
|
|
||||||
{
|
|
||||||
if (masterKey.Length * 8 < keySize)
|
|
||||||
throw new CryptographicException("masterKey size=" + masterKey.Length);
|
|
||||||
|
|
||||||
decRoundKeys = null;
|
|
||||||
encRoundKeys = null;
|
|
||||||
masterKey = (byte[])masterKey.Clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetupEncRoundKeys()
|
|
||||||
{
|
|
||||||
if (keySize == 0)
|
|
||||||
throw new CryptographicException("keySize");
|
|
||||||
if (masterKey == null)
|
|
||||||
throw new CryptographicException("masterKey");
|
|
||||||
if (encRoundKeys == null)
|
|
||||||
encRoundKeys = new uint[4 * (numberOfRounds + 1)];
|
|
||||||
|
|
||||||
decRoundKeys = null;
|
|
||||||
DoEncKeySetup(masterKey, encRoundKeys, keySize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetupDecRoundKeys()
|
|
||||||
{
|
|
||||||
if (keySize == 0)
|
|
||||||
throw new CryptographicException("keySize");
|
|
||||||
|
|
||||||
if (encRoundKeys == null)
|
|
||||||
{
|
|
||||||
if (masterKey == null)
|
|
||||||
{
|
|
||||||
throw new CryptographicException("masterKey");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SetupEncRoundKeys();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
decRoundKeys = (uint[])encRoundKeys.Clone();
|
|
||||||
DoDecKeySetup(masterKey, decRoundKeys, keySize);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetupRoundKeys()
|
|
||||||
{
|
|
||||||
SetupDecRoundKeys();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void DoCrypt(byte[] i, int ioffset, uint[] rk, int nr, byte[] o, int ooffset)
|
|
||||||
{
|
|
||||||
uint t0, t1, t2, t3, j = 0;
|
|
||||||
|
|
||||||
t0 = ToInt(i[0 + ioffset], i[1 + ioffset], i[2 + ioffset], i[3 + ioffset]);
|
|
||||||
t1 = ToInt(i[4 + ioffset], i[5 + ioffset], i[6 + ioffset], i[7 + ioffset]);
|
|
||||||
t2 = ToInt(i[8 + ioffset], i[9 + ioffset], i[10 + ioffset], i[11 + ioffset]);
|
|
||||||
t3 = ToInt(i[12 + ioffset], i[13 + ioffset], i[14 + ioffset], i[15 + ioffset]);
|
|
||||||
|
|
||||||
for (int r = 1; r < nr / 2; r++)
|
|
||||||
{
|
|
||||||
t0 ^= rk[j++]; t1 ^= rk[j++]; t2 ^= rk[j++]; t3 ^= rk[j++];
|
|
||||||
t0 = TS1[(t0 >> 24) & 0xff] ^ TS2[(t0 >> 16) & 0xff] ^ TX1[(t0 >> 8) & 0xff] ^ TX2[t0 & 0xff];
|
|
||||||
t1 = TS1[(t1 >> 24) & 0xff] ^ TS2[(t1 >> 16) & 0xff] ^ TX1[(t1 >> 8) & 0xff] ^ TX2[t1 & 0xff];
|
|
||||||
t2 = TS1[(t2 >> 24) & 0xff] ^ TS2[(t2 >> 16) & 0xff] ^ TX1[(t2 >> 8) & 0xff] ^ TX2[t2 & 0xff];
|
|
||||||
t3 = TS1[(t3 >> 24) & 0xff] ^ TS2[(t3 >> 16) & 0xff] ^ TX1[(t3 >> 8) & 0xff] ^ TX2[t3 & 0xff];
|
|
||||||
t1 ^= t2; t2 ^= t3; t0 ^= t1; t3 ^= t1; t2 ^= t0; t1 ^= t2;
|
|
||||||
t1 = Badc(t1); t2 = Cdab(t2); t3 = Dcba(t3);
|
|
||||||
t1 ^= t2; t2 ^= t3; t0 ^= t1; t3 ^= t1; t2 ^= t0; t1 ^= t2;
|
|
||||||
|
|
||||||
t0 ^= rk[j++]; t1 ^= rk[j++]; t2 ^= rk[j++]; t3 ^= rk[j++];
|
|
||||||
t0 = TX1[(t0 >> 24) & 0xff] ^ TX2[(t0 >> 16) & 0xff] ^ TS1[(t0 >> 8) & 0xff] ^ TS2[t0 & 0xff];
|
|
||||||
t1 = TX1[(t1 >> 24) & 0xff] ^ TX2[(t1 >> 16) & 0xff] ^ TS1[(t1 >> 8) & 0xff] ^ TS2[t1 & 0xff];
|
|
||||||
t2 = TX1[(t2 >> 24) & 0xff] ^ TX2[(t2 >> 16) & 0xff] ^ TS1[(t2 >> 8) & 0xff] ^ TS2[t2 & 0xff];
|
|
||||||
t3 = TX1[(t3 >> 24) & 0xff] ^ TX2[(t3 >> 16) & 0xff] ^ TS1[(t3 >> 8) & 0xff] ^ TS2[t3 & 0xff];
|
|
||||||
t1 ^= t2; t2 ^= t3; t0 ^= t1; t3 ^= t1; t2 ^= t0; t1 ^= t2;
|
|
||||||
t3 = Badc(t3); t0 = Cdab(t0); t1 = Dcba(t1);
|
|
||||||
t1 ^= t2; t2 ^= t3; t0 ^= t1; t3 ^= t1; t2 ^= t0; t1 ^= t2;
|
|
||||||
}
|
|
||||||
t0 ^= rk[j++]; t1 ^= rk[j++]; t2 ^= rk[j++]; t3 ^= rk[j++];
|
|
||||||
t0 = TS1[(t0 >> 24) & 0xff] ^ TS2[(t0 >> 16) & 0xff] ^ TX1[(t0 >> 8) & 0xff] ^ TX2[t0 & 0xff];
|
|
||||||
t1 = TS1[(t1 >> 24) & 0xff] ^ TS2[(t1 >> 16) & 0xff] ^ TX1[(t1 >> 8) & 0xff] ^ TX2[t1 & 0xff];
|
|
||||||
t2 = TS1[(t2 >> 24) & 0xff] ^ TS2[(t2 >> 16) & 0xff] ^ TX1[(t2 >> 8) & 0xff] ^ TX2[t2 & 0xff];
|
|
||||||
t3 = TS1[(t3 >> 24) & 0xff] ^ TS2[(t3 >> 16) & 0xff] ^ TX1[(t3 >> 8) & 0xff] ^ TX2[t3 & 0xff];
|
|
||||||
t1 ^= t2; t2 ^= t3; t0 ^= t1; t3 ^= t1; t2 ^= t0; t1 ^= t2;
|
|
||||||
t1 = Badc(t1); t2 = Cdab(t2); t3 = Dcba(t3);
|
|
||||||
t1 ^= t2; t2 ^= t3; t0 ^= t1; t3 ^= t1; t2 ^= t0; t1 ^= t2;
|
|
||||||
|
|
||||||
t0 ^= rk[j++]; t1 ^= rk[j++]; t2 ^= rk[j++]; t3 ^= rk[j++];
|
|
||||||
o[0 + ooffset] = (byte)(X1[0xff & (t0 >> 24)] ^ (rk[j] >> 24));
|
|
||||||
o[1 + ooffset] = (byte)(X2[0xff & (t0 >> 16)] ^ (rk[j] >> 16));
|
|
||||||
o[2 + ooffset] = (byte)(S1[0xff & (t0 >> 8)] ^ (rk[j] >> 8));
|
|
||||||
o[3 + ooffset] = (byte)(S2[0xff & (t0)] ^ (rk[j]));
|
|
||||||
o[4 + ooffset] = (byte)(X1[0xff & (t1 >> 24)] ^ (rk[j + 1] >> 24));
|
|
||||||
o[5 + ooffset] = (byte)(X2[0xff & (t1 >> 16)] ^ (rk[j + 1] >> 16));
|
|
||||||
o[6 + ooffset] = (byte)(S1[0xff & (t1 >> 8)] ^ (rk[j + 1] >> 8));
|
|
||||||
o[7 + ooffset] = (byte)(S2[0xff & (t1)] ^ (rk[j + 1]));
|
|
||||||
o[8 + ooffset] = (byte)(X1[0xff & (t2 >> 24)] ^ (rk[j + 2] >> 24));
|
|
||||||
o[9 + ooffset] = (byte)(X2[0xff & (t2 >> 16)] ^ (rk[j + 2] >> 16));
|
|
||||||
o[10 + ooffset] = (byte)(S1[0xff & (t2 >> 8)] ^ (rk[j + 2] >> 8));
|
|
||||||
o[11 + ooffset] = (byte)(S2[0xff & (t2)] ^ (rk[j + 2]));
|
|
||||||
o[12 + ooffset] = (byte)(X1[0xff & (t3 >> 24)] ^ (rk[j + 3] >> 24));
|
|
||||||
o[13 + ooffset] = (byte)(X2[0xff & (t3 >> 16)] ^ (rk[j + 3] >> 16));
|
|
||||||
o[14 + ooffset] = (byte)(S1[0xff & (t3 >> 8)] ^ (rk[j + 3] >> 8));
|
|
||||||
o[15 + ooffset] = (byte)(S2[0xff & (t3)] ^ (rk[j + 3]));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Encrypt(byte[] i, int ioffset, byte[] o, int ooffset)
|
|
||||||
{
|
|
||||||
if (keySize == 0)
|
|
||||||
throw new CryptographicException("keySize");
|
|
||||||
|
|
||||||
if (encRoundKeys == null)
|
|
||||||
{
|
|
||||||
if (masterKey == null)
|
|
||||||
{
|
|
||||||
throw new CryptographicException("masterKey");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SetupEncRoundKeys();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DoCrypt(i, ioffset, encRoundKeys, numberOfRounds, o, ooffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] Encrypt(byte[] i, int ioffset)
|
|
||||||
{
|
|
||||||
byte[] o = new byte[16];
|
|
||||||
Encrypt(i, ioffset, o, 0);
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Decrypt(byte[] i, int ioffset, byte[] o, int ooffset)
|
|
||||||
{
|
|
||||||
if (keySize == 0)
|
|
||||||
throw new CryptographicException("keySize");
|
|
||||||
|
|
||||||
if (decRoundKeys == null)
|
|
||||||
{
|
|
||||||
if (masterKey == null)
|
|
||||||
{
|
|
||||||
throw new CryptographicException("masterKey");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SetupDecRoundKeys();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DoCrypt(i, ioffset, decRoundKeys, numberOfRounds, o, ooffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] Decrypt(byte[] i, int ioffset)
|
|
||||||
{
|
|
||||||
byte[] o = new byte[16];
|
|
||||||
Decrypt(i, ioffset, o, 0);
|
|
||||||
|
|
||||||
return o;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void DoEncKeySetup(byte[] mk, uint[] rk, int keyBits)
|
|
||||||
{
|
|
||||||
uint t0, t1, t2, t3;
|
|
||||||
int q, j = 0;
|
|
||||||
uint[] w0 = new uint[4];
|
|
||||||
uint[] w1 = new uint[4];
|
|
||||||
uint[] w2 = new uint[4];
|
|
||||||
uint[] w3 = new uint[4];
|
|
||||||
|
|
||||||
w0[0] = ToInt(mk[0], mk[1], mk[2], mk[3]);
|
|
||||||
w0[1] = ToInt(mk[4], mk[5], mk[6], mk[7]);
|
|
||||||
w0[2] = ToInt(mk[8], mk[9], mk[10], mk[11]);
|
|
||||||
w0[3] = ToInt(mk[12], mk[13], mk[14], mk[15]);
|
|
||||||
|
|
||||||
q = (keyBits - 128) / 64;
|
|
||||||
t0 = w0[0] ^ KRK[q, 0]; t1 = w0[1] ^ KRK[q, 1];
|
|
||||||
t2 = w0[2] ^ KRK[q, 2]; t3 = w0[3] ^ KRK[q, 3];
|
|
||||||
t0 = TS1[(t0 >> 24) & 0xff] ^ TS2[(t0 >> 16) & 0xff] ^ TX1[(t0 >> 8) & 0xff] ^ TX2[t0 & 0xff];
|
|
||||||
t1 = TS1[(t1 >> 24) & 0xff] ^ TS2[(t1 >> 16) & 0xff] ^ TX1[(t1 >> 8) & 0xff] ^ TX2[t1 & 0xff];
|
|
||||||
t2 = TS1[(t2 >> 24) & 0xff] ^ TS2[(t2 >> 16) & 0xff] ^ TX1[(t2 >> 8) & 0xff] ^ TX2[t2 & 0xff];
|
|
||||||
t3 = TS1[(t3 >> 24) & 0xff] ^ TS2[(t3 >> 16) & 0xff] ^ TX1[(t3 >> 8) & 0xff] ^ TX2[t3 & 0xff];
|
|
||||||
t1 ^= t2; t2 ^= t3; t0 ^= t1; t3 ^= t1; t2 ^= t0; t1 ^= t2;
|
|
||||||
t1 = Badc(t1); t2 = Cdab(t2); t3 = Dcba(t3);
|
|
||||||
t1 ^= t2; t2 ^= t3; t0 ^= t1; t3 ^= t1; t2 ^= t0; t1 ^= t2;
|
|
||||||
|
|
||||||
if (keyBits > 128)
|
|
||||||
{
|
|
||||||
w1[0] = ToInt(mk[16], mk[17], mk[18], mk[19]);
|
|
||||||
w1[1] = ToInt(mk[20], mk[21], mk[22], mk[23]);
|
|
||||||
if (keyBits > 192)
|
|
||||||
{
|
|
||||||
w1[2] = ToInt(mk[24], mk[25], mk[26], mk[27]);
|
|
||||||
w1[3] = ToInt(mk[28], mk[29], mk[30], mk[31]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
w1[2] = w1[3] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
w1[0] = w1[1] = w1[2] = w1[3] = 0;
|
|
||||||
}
|
|
||||||
w1[0] ^= t0; w1[1] ^= t1; w1[2] ^= t2; w1[3] ^= t3;
|
|
||||||
t0 = w1[0]; t1 = w1[1]; t2 = w1[2]; t3 = w1[3];
|
|
||||||
|
|
||||||
q = (q == 2) ? 0 : (q + 1);
|
|
||||||
t0 ^= KRK[q, 0]; t1 ^= KRK[q, 1]; t2 ^= KRK[q, 2]; t3 ^= KRK[q, 3];
|
|
||||||
t0 = TX1[(t0 >> 24) & 0xff] ^ TX2[(t0 >> 16) & 0xff] ^ TS1[(t0 >> 8) & 0xff] ^ TS2[t0 & 0xff];
|
|
||||||
t1 = TX1[(t1 >> 24) & 0xff] ^ TX2[(t1 >> 16) & 0xff] ^ TS1[(t1 >> 8) & 0xff] ^ TS2[t1 & 0xff];
|
|
||||||
t2 = TX1[(t2 >> 24) & 0xff] ^ TX2[(t2 >> 16) & 0xff] ^ TS1[(t2 >> 8) & 0xff] ^ TS2[t2 & 0xff];
|
|
||||||
t3 = TX1[(t3 >> 24) & 0xff] ^ TX2[(t3 >> 16) & 0xff] ^ TS1[(t3 >> 8) & 0xff] ^ TS2[t3 & 0xff];
|
|
||||||
t1 ^= t2; t2 ^= t3; t0 ^= t1; t3 ^= t1; t2 ^= t0; t1 ^= t2;
|
|
||||||
t3 = Badc(t3); t0 = Cdab(t0); t1 = Dcba(t1);
|
|
||||||
t1 ^= t2; t2 ^= t3; t0 ^= t1; t3 ^= t1; t2 ^= t0; t1 ^= t2;
|
|
||||||
t0 ^= w0[0]; t1 ^= w0[1]; t2 ^= w0[2]; t3 ^= w0[3];
|
|
||||||
w2[0] = t0; w2[1] = t1; w2[2] = t2; w2[3] = t3;
|
|
||||||
|
|
||||||
q = (q == 2) ? 0 : (q + 1);
|
|
||||||
t0 ^= KRK[q, 0]; t1 ^= KRK[q, 1]; t2 ^= KRK[q, 2]; t3 ^= KRK[q, 3];
|
|
||||||
t0 = TS1[(t0 >> 24) & 0xff] ^ TS2[(t0 >> 16) & 0xff] ^ TX1[(t0 >> 8) & 0xff] ^ TX2[t0 & 0xff];
|
|
||||||
t1 = TS1[(t1 >> 24) & 0xff] ^ TS2[(t1 >> 16) & 0xff] ^ TX1[(t1 >> 8) & 0xff] ^ TX2[t1 & 0xff];
|
|
||||||
t2 = TS1[(t2 >> 24) & 0xff] ^ TS2[(t2 >> 16) & 0xff] ^ TX1[(t2 >> 8) & 0xff] ^ TX2[t2 & 0xff];
|
|
||||||
t3 = TS1[(t3 >> 24) & 0xff] ^ TS2[(t3 >> 16) & 0xff] ^ TX1[(t3 >> 8) & 0xff] ^ TX2[t3 & 0xff];
|
|
||||||
t1 ^= t2; t2 ^= t3; t0 ^= t1; t3 ^= t1; t2 ^= t0; t1 ^= t2;
|
|
||||||
t1 = Badc(t1); t2 = Cdab(t2); t3 = Dcba(t3);
|
|
||||||
t1 ^= t2; t2 ^= t3; t0 ^= t1; t3 ^= t1; t2 ^= t0; t1 ^= t2;
|
|
||||||
w3[0] = t0 ^ w1[0]; w3[1] = t1 ^ w1[1]; w3[2] = t2 ^ w1[2]; w3[3] = t3 ^ w1[3];
|
|
||||||
|
|
||||||
Gsrk(w0, w1, 19, rk, j); j += 4;
|
|
||||||
Gsrk(w1, w2, 19, rk, j); j += 4;
|
|
||||||
Gsrk(w2, w3, 19, rk, j); j += 4;
|
|
||||||
Gsrk(w3, w0, 19, rk, j); j += 4;
|
|
||||||
Gsrk(w0, w1, 31, rk, j); j += 4;
|
|
||||||
Gsrk(w1, w2, 31, rk, j); j += 4;
|
|
||||||
Gsrk(w2, w3, 31, rk, j); j += 4;
|
|
||||||
Gsrk(w3, w0, 31, rk, j); j += 4;
|
|
||||||
Gsrk(w0, w1, 67, rk, j); j += 4;
|
|
||||||
Gsrk(w1, w2, 67, rk, j); j += 4;
|
|
||||||
Gsrk(w2, w3, 67, rk, j); j += 4;
|
|
||||||
Gsrk(w3, w0, 67, rk, j); j += 4;
|
|
||||||
Gsrk(w0, w1, 97, rk, j); j += 4;
|
|
||||||
if (keyBits > 128)
|
|
||||||
{
|
|
||||||
Gsrk(w1, w2, 97, rk, j); j += 4;
|
|
||||||
Gsrk(w2, w3, 97, rk, j); j += 4;
|
|
||||||
}
|
|
||||||
if (keyBits > 192)
|
|
||||||
{
|
|
||||||
Gsrk(w3, w0, 97, rk, j); j += 4;
|
|
||||||
Gsrk(w0, w1, 109, rk, j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main bulk of the decryption key setup method. Here we assume that
|
|
||||||
* the int array rk already contains the encryption round keys.
|
|
||||||
* @param mk the master key
|
|
||||||
* @param rk the array which contains the encryption round keys at the
|
|
||||||
* beginning of the method execution. At the end of method execution
|
|
||||||
* this will hold the decryption round keys.
|
|
||||||
* @param keyBits the length of the master key
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private static void DoDecKeySetup(byte[] mk, uint[] rk, int keyBits)
|
|
||||||
{
|
|
||||||
int a = 0, z;
|
|
||||||
uint[] t = new uint[4];
|
|
||||||
|
|
||||||
z = 32 + keyBits / 8;
|
|
||||||
SwapBlocks(rk, 0, z);
|
|
||||||
a += 4; z -= 4;
|
|
||||||
|
|
||||||
for (; a < z; a += 4, z -= 4)
|
|
||||||
SwapAndDiffuse(rk, a, z, t);
|
|
||||||
Diff(rk, a, t, 0);
|
|
||||||
rk[a] = t[0]; rk[a + 1] = t[1]; rk[a + 2] = t[2]; rk[a + 3] = t[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint ToInt(byte b0, byte b1, byte b2, byte b3)
|
|
||||||
{
|
|
||||||
return (uint)((b0 & 0xff) << 24 ^ (b1 & 0xff) << 16 ^ (b2 & 0xff) << 8 ^ b3 & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint M(uint t)
|
|
||||||
{
|
|
||||||
return 0x00010101 * ((t >> 24) & 0xff) ^ 0x01000101 * ((t >> 16) & 0xff) ^
|
|
||||||
0x01010001 * ((t >> 8) & 0xff) ^ 0x01010100 * (t & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
// private static final int ms(int t) {
|
|
||||||
// return TS1[(t>>>24)&0xff]^TS2[(t>>>16)&0xff]^TX1[(t>>>8)&0xff]^TX2[t&0xff];
|
|
||||||
// }
|
|
||||||
// private static final int mx(int t) {
|
|
||||||
// return TX1[(t>>>24)&0xff]^TX2[(t>>>16)&0xff]^TS1[(t>>>8)&0xff]^TS2[t&0xff];
|
|
||||||
// }
|
|
||||||
private static uint Badc(uint t)
|
|
||||||
{
|
|
||||||
return ((t << 8) & 0xff00ff00) ^ ((t >> 8) & 0x00ff00ff);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint Cdab(uint t)
|
|
||||||
{
|
|
||||||
return ((t << 16) & 0xffff0000) ^ ((t >> 16) & 0x0000ffff);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint Dcba(uint t)
|
|
||||||
{
|
|
||||||
return (t & 0x000000ff) << 24 ^ (t & 0x0000ff00) << 8 ^ (t & 0x00ff0000) >> 8 ^ (t & 0xff000000) >> 24;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void Gsrk(uint[] x, uint[] y, int rot, uint[] rk, int offset)
|
|
||||||
{
|
|
||||||
int q = 4 - (rot / 32), r = rot % 32, s = 32 - r;
|
|
||||||
|
|
||||||
rk[offset] = x[0] ^ y[(q) % 4] >> r ^ y[(q + 3) % 4] << s;
|
|
||||||
rk[offset + 1] = x[1] ^ y[(q + 1) % 4] >> r ^ y[(q) % 4] << s;
|
|
||||||
rk[offset + 2] = x[2] ^ y[(q + 2) % 4] >> r ^ y[(q + 1) % 4] << s;
|
|
||||||
rk[offset + 3] = x[3] ^ y[(q + 3) % 4] >> r ^ y[(q + 2) % 4] << s;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void Diff(uint[] i, int offset1, uint[] o, int offset2)
|
|
||||||
{
|
|
||||||
uint t0, t1, t2, t3;
|
|
||||||
|
|
||||||
t0 = M(i[offset1]); t1 = M(i[offset1 + 1]); t2 = M(i[offset1 + 2]); t3 = M(i[offset1 + 3]);
|
|
||||||
t1 ^= t2; t2 ^= t3; t0 ^= t1; t3 ^= t1; t2 ^= t0; t1 ^= t2;
|
|
||||||
t1 = Badc(t1); t2 = Cdab(t2); t3 = Dcba(t3);
|
|
||||||
t1 ^= t2; t2 ^= t3; t0 ^= t1; t3 ^= t1; t2 ^= t0; t1 ^= t2;
|
|
||||||
o[offset2] = t0; o[offset2 + 1] = t1; o[offset2 + 2] = t2; o[offset2 + 3] = t3;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void SwapBlocks(uint[] arr, int offset1, int offset2)
|
|
||||||
{
|
|
||||||
uint t;
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
t = arr[offset1 + i];
|
|
||||||
arr[offset1 + i] = arr[offset2 + i];
|
|
||||||
arr[offset2 + i] = t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void SwapAndDiffuse(uint[] arr, int offset1, int offset2, uint[] tmp)
|
|
||||||
{
|
|
||||||
Diff(arr, offset1, tmp, 0);
|
|
||||||
Diff(arr, offset2, arr, offset1);
|
|
||||||
arr[offset2] = tmp[0]; arr[offset2 + 1] = tmp[1];
|
|
||||||
arr[offset2 + 2] = tmp[2]; arr[offset2 + 3] = tmp[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ECB
|
|
||||||
{
|
|
||||||
private static readonly int BLOCK_SIZE = 16;
|
|
||||||
private ARIA engine = null;
|
|
||||||
|
|
||||||
public ECB(byte[] key)
|
|
||||||
{
|
|
||||||
Init(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ECB(string key)
|
|
||||||
{
|
|
||||||
Init(CreateKey(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Init(byte[] key)
|
|
||||||
{
|
|
||||||
engine = new ARIA(key.Length * 8);
|
|
||||||
engine.SetKey(key);
|
|
||||||
engine.SetupRoundKeys();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// allowed key size (bit): 128, 192, 256
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="key"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private byte[] CreateKey(string key)
|
|
||||||
{
|
|
||||||
SHA256 hasher = SHA256.Create();
|
|
||||||
byte[] hashData = hasher.ComputeHash(Encoding.Default.GetBytes(key));
|
|
||||||
|
|
||||||
return hashData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] Encrypt(byte[] data)
|
|
||||||
{
|
|
||||||
byte[] indata = AnsiX923Padding.AddPadding(data, BLOCK_SIZE);
|
|
||||||
byte[] outdata = new byte[indata.Length];
|
|
||||||
|
|
||||||
for (int i = 0; i < indata.Length; i += BLOCK_SIZE)
|
|
||||||
{
|
|
||||||
engine.Encrypt(indata, i, outdata, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return outdata;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] Decrypt(byte[] data)
|
|
||||||
{
|
|
||||||
byte[] outdata = new byte[data.Length];
|
|
||||||
|
|
||||||
for (int i = 0; i < data.Length; i += BLOCK_SIZE)
|
|
||||||
{
|
|
||||||
engine.Decrypt(data, i, outdata, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return AnsiX923Padding.RemovePadding(outdata, BLOCK_SIZE, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,132 +0,0 @@
|
||||||
/*
|
|
||||||
* WelsonJS.Toolkit: WelsonJS native component
|
|
||||||
*
|
|
||||||
* filename:
|
|
||||||
* AnsiX923Padding.cs
|
|
||||||
*
|
|
||||||
* description:
|
|
||||||
* AnsiX923Padding implementation
|
|
||||||
*
|
|
||||||
* website:
|
|
||||||
* - https://github.com/gnh1201/welsonjs
|
|
||||||
* - https://catswords.social/@catswords_oss
|
|
||||||
* - https://teams.live.com/l/community/FEACHncAhq8ldnojAI
|
|
||||||
* - https://discord.gg/XKG5CjtXEj
|
|
||||||
*
|
|
||||||
* authors:
|
|
||||||
* - Namhyeon Go (@gnh1201) <abuse@catswords.net>
|
|
||||||
*
|
|
||||||
* references:
|
|
||||||
* - https://github.com/eGovFrame/egovframework.rte.root/blob/master/Foundation/egovframework.rte.fdl.crypto/src/main/java/egovframework/rte/fdl/cryptography/impl/aria/AnsiX923Padding.java
|
|
||||||
* - ChatGPT prompt "AnsiX923Padding with C#" (chatgpt.com)
|
|
||||||
* - ChatGPT prompt "AnsiX923Padding with C#, Add a flag to decide how to handle possible errors when removing padding." (chatgpt.com)
|
|
||||||
*
|
|
||||||
* license:
|
|
||||||
* GPLv3 or MS-RL(Microsoft Reciprocal License)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace WelsonJS.Cryptography
|
|
||||||
{
|
|
||||||
class AnsiX923Padding
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Add ANSI X.923 padding to the input data to make it a multiple of the block size.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="data">The data to be padded.</param>
|
|
||||||
/// <param name="blockSize">The block size to pad to.</param>
|
|
||||||
/// <returns>Padded data with ANSI X.923 padding.</returns>
|
|
||||||
public static byte[] AddPadding(byte[] data, int blockSize)
|
|
||||||
{
|
|
||||||
int paddingLength = blockSize - (data.Length % blockSize);
|
|
||||||
|
|
||||||
// If the data is already a multiple of the block size, no padding is needed
|
|
||||||
if (paddingLength == blockSize)
|
|
||||||
{
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] paddedData = new byte[data.Length + paddingLength];
|
|
||||||
|
|
||||||
// Copy original data into the padded array
|
|
||||||
Array.Copy(data, paddedData, data.Length);
|
|
||||||
|
|
||||||
// Fill with 0x00 bytes, and the last byte is the padding length
|
|
||||||
for (int i = data.Length; i < paddedData.Length - 1; i++)
|
|
||||||
{
|
|
||||||
paddedData[i] = 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Last byte is the padding length
|
|
||||||
paddedData[paddedData.Length - 1] = (byte)paddingLength;
|
|
||||||
|
|
||||||
return paddedData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes ANSI X.923 padding from the given data.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="data">The input data, including padding.</param>
|
|
||||||
/// <param name="blockSize">The block size used for padding.</param>
|
|
||||||
/// <param name="ignoreErrors">If true, ignores errors and attempts to process the input data as-is.</param>
|
|
||||||
/// <returns>The unpadded data as a byte array.</returns>
|
|
||||||
/// <exception cref="ArgumentException">Thrown if the input data or padding is invalid and ignoreErrors is false.</exception>
|
|
||||||
public static byte[] RemovePadding(byte[] data, int blockSize, bool ignoreErrors = false)
|
|
||||||
{
|
|
||||||
// Check for null or empty data
|
|
||||||
if (data == null || data.Length == 0)
|
|
||||||
{
|
|
||||||
if (ignoreErrors)
|
|
||||||
{
|
|
||||||
return new byte[] { };
|
|
||||||
}
|
|
||||||
throw new ArgumentException("Input data cannot be null or empty.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure the data length is a multiple of the block size
|
|
||||||
if (data.Length % blockSize != 0)
|
|
||||||
{
|
|
||||||
if (ignoreErrors)
|
|
||||||
{
|
|
||||||
// Return the original data if errors are ignored
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
throw new ArgumentException("Input data length must be a multiple of the block size.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve the padding length from the last byte
|
|
||||||
int paddingLength = data[data.Length - 1];
|
|
||||||
|
|
||||||
// Validate padding length
|
|
||||||
if (paddingLength <= 0 || paddingLength > blockSize)
|
|
||||||
{
|
|
||||||
if (!ignoreErrors)
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"Invalid padding length: {paddingLength}. Must be between 1 and {blockSize}.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Treat padding length as 0 and return the full data
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate the padding region (last paddingLength - 1 bytes must be 0x00)
|
|
||||||
for (int i = data.Length - paddingLength; i < data.Length - 1; i++)
|
|
||||||
{
|
|
||||||
if (data[i] != 0x00)
|
|
||||||
{
|
|
||||||
if (!ignoreErrors)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Invalid padding detected. Expected padding bytes to be 0x00.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract unpadded data
|
|
||||||
byte[] unpaddedData = new byte[data.Length - paddingLength];
|
|
||||||
Array.Copy(data, unpaddedData, unpaddedData.Length);
|
|
||||||
|
|
||||||
return unpaddedData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,38 +5,34 @@
|
||||||
* HIGHT.cs
|
* HIGHT.cs
|
||||||
*
|
*
|
||||||
* description:
|
* description:
|
||||||
* HIGHT(ISO/IEC 18033-3) cryptography algorithm implementation
|
* HIGHT(ISO/IEC 18033-3) cryptography algorithm (ECB mode) implementation for WelsonJS
|
||||||
*
|
*
|
||||||
* website:
|
* website:
|
||||||
* - https://github.com/gnh1201/welsonjs
|
* - https://github.com/gnh1201/welsonjs
|
||||||
* - https://catswords.social/@catswords_oss
|
* - https://catswords.social/@catswords_oss
|
||||||
* - https://teams.live.com/l/community/FEACHncAhq8ldnojAI
|
* - https://teams.live.com/l/community/FEACHncAhq8ldnojAI
|
||||||
* - https://discord.gg/XKG5CjtXEj
|
|
||||||
*
|
*
|
||||||
* authors:
|
* author:
|
||||||
* - Namhyeon Go (@gnh1201) <abuse@catswords.net>
|
* - Namhyeon Go <abuse@catswords.net>
|
||||||
* - @chandong83 (github.com)
|
* - @chandong83 (github.com) - Original author of CryptoHIGHT.cs
|
||||||
* - KISA(Korea Internet & Security Agency) (kisa.or.kr)
|
* - KISA(Korea Internet & Security Agency)
|
||||||
* - Korea Unversity (www.korea.ac.kr)
|
|
||||||
*
|
*
|
||||||
* references:
|
* references:
|
||||||
* - https://seed.kisa.or.kr/kisa/algorithm/EgovHightInfo.do
|
|
||||||
* - https://github.com/chandong83/csharp_crypto_hight_ecb_examples
|
* - https://github.com/chandong83/csharp_crypto_hight_ecb_examples
|
||||||
* - https://blog.naver.com/chandong83/222198351602
|
* - https://blog.naver.com/chandong83/222198351602
|
||||||
|
* - https://seed.kisa.or.kr/kisa/algorithm/EgovHightInfo.do
|
||||||
* - https://www.iso.org/standard/54531.html
|
* - https://www.iso.org/standard/54531.html
|
||||||
* - https://ics.catswords.net/HIGHT-algorithm-specification-english.pdf
|
|
||||||
* - https://ics.catswords.net/HIGHT-algorithm-specification-korean.pdf
|
|
||||||
* - https://ics.catswords.net/HIGHT-sourcecode-explanation.pdf
|
|
||||||
*
|
*
|
||||||
* license:
|
* license:
|
||||||
* GPLv3 or MS-RL(Microsoft Reciprocal License)
|
* GPLv3 or MS-RL(Microsoft Reciprocal License)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace WelsonJS.Cryptography
|
namespace WelsonJS.Cryptography
|
||||||
{
|
{
|
||||||
public class HIGHT
|
public static class HIGHT
|
||||||
{
|
{
|
||||||
private static readonly byte[] hightDelta = {
|
private static readonly byte[] hightDelta = {
|
||||||
0x5A,0x6D,0x36,0x1B,0x0D,0x06,0x03,0x41,
|
0x5A,0x6D,0x36,0x1B,0x0D,0x06,0x03,0x41,
|
||||||
|
@ -239,6 +235,24 @@ namespace WelsonJS.Cryptography
|
||||||
dataOut[6] = (byte)((xx[6] ^ scheduleKey[3]) & 0xFF);
|
dataOut[6] = (byte)((xx[6] ^ scheduleKey[3]) & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void debugPrintHex(byte[] dat)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < dat.Length; i++)
|
||||||
|
{
|
||||||
|
Console.Write(string.Format("0x{0:x2}, ", dat[i]));
|
||||||
|
if (((i + 1) % 16) == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Console.WriteLine("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void debugPrintLine(string str)
|
||||||
|
{
|
||||||
|
Console.WriteLine(str);
|
||||||
|
}
|
||||||
|
|
||||||
void EncryptBlock(byte[] dataIn, byte[] dataOut)
|
void EncryptBlock(byte[] dataIn, byte[] dataOut)
|
||||||
{
|
{
|
||||||
byte[] xx = new byte[8];
|
byte[] xx = new byte[8];
|
||||||
|
@ -303,7 +317,6 @@ namespace WelsonJS.Cryptography
|
||||||
dataOut[4] = (byte)((xx[5] + scheduleKey[6]) & 0xFF);
|
dataOut[4] = (byte)((xx[5] + scheduleKey[6]) & 0xFF);
|
||||||
dataOut[6] = (byte)((xx[7] ^ scheduleKey[7]) & 0xFF);
|
dataOut[6] = (byte)((xx[7] ^ scheduleKey[7]) & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] Encrypt(byte[] dataIn)
|
public byte[] Encrypt(byte[] dataIn)
|
||||||
{
|
{
|
||||||
int length;
|
int length;
|
||||||
|
@ -333,7 +346,6 @@ namespace WelsonJS.Cryptography
|
||||||
}
|
}
|
||||||
return dataOut;
|
return dataOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] Decrypt(byte[] dataIn)
|
public byte[] Decrypt(byte[] dataIn)
|
||||||
{
|
{
|
||||||
int length;
|
int length;
|
||||||
|
@ -363,7 +375,7 @@ namespace WelsonJS.Cryptography
|
||||||
return dataOut;
|
return dataOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Test()
|
public void test()
|
||||||
{
|
{
|
||||||
byte[] dataIn = new byte[15];
|
byte[] dataIn = new byte[15];
|
||||||
byte[] dataOut = new byte[15];
|
byte[] dataOut = new byte[15];
|
||||||
|
@ -372,17 +384,17 @@ namespace WelsonJS.Cryptography
|
||||||
{
|
{
|
||||||
dataIn[i] = (byte)i;
|
dataIn[i] = (byte)i;
|
||||||
}
|
}
|
||||||
Console.WriteLine("schedule key data");
|
debugPrintLine("schedule key data");
|
||||||
Console.WriteLine(string.Format("0x{0:x2}", scheduleKey));
|
debugPrintHex(scheduleKey);
|
||||||
|
|
||||||
dataOut = Encrypt(dataIn);
|
dataOut = Encrypt(dataIn);
|
||||||
dataOut2 = Decrypt(dataOut);
|
dataOut2 = Decrypt(dataOut);
|
||||||
Console.WriteLine("origin data");
|
debugPrintLine("origin data");
|
||||||
Console.WriteLine(string.Format("0x{0:x2}", dataIn));
|
debugPrintHex(dataIn);
|
||||||
Console.WriteLine("encryption data");
|
debugPrintLine("encryption data");
|
||||||
Console.WriteLine(string.Format("0x{0:x2}", dataOut));
|
debugPrintHex(dataOut);
|
||||||
Console.WriteLine("decryption data");
|
debugPrintLine("decryption data");
|
||||||
Console.WriteLine(string.Format("0x{0:x2}", dataOut2));
|
debugPrintHex(dataOut2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,349 +0,0 @@
|
||||||
/*
|
|
||||||
* WelsonJS.Toolkit: WelsonJS native component
|
|
||||||
*
|
|
||||||
* filename:
|
|
||||||
* LEA.cs
|
|
||||||
*
|
|
||||||
* description:
|
|
||||||
* LEA(KS X 3246:2016) cryptography algorithm implementation (Experimental)
|
|
||||||
*
|
|
||||||
* website:
|
|
||||||
* - https://github.com/gnh1201/welsonjs
|
|
||||||
* - https://catswords.social/@catswords_oss
|
|
||||||
* - https://teams.live.com/l/community/FEACHncAhq8ldnojAI
|
|
||||||
* - https://discord.gg/XKG5CjtXEj
|
|
||||||
*
|
|
||||||
* authors:
|
|
||||||
* - Namhyeon Go (@gnh1201) <abuse@catswords.net>
|
|
||||||
* - KISA(Korea Internet & Security Agency) (kisa.or.kr)
|
|
||||||
* - National Security Research Institute (NSRI)
|
|
||||||
*
|
|
||||||
* references:
|
|
||||||
* - https://seed.kisa.or.kr/kisa/Board/20/detailView.do
|
|
||||||
* - https://committee.tta.or.kr/data/standard_view.jsp?order=t.kor_standard&by=asc&pk_num=TTAK.KO-12.0223&commit_code=TC5
|
|
||||||
* - https://ics.catswords.net/LEA%20A%20128-Bit%20Block%20Cipher%20Datasheets-Korean.pdf
|
|
||||||
* - https://ics.catswords.net/LEA%20A%20128-Bit%20Block%20Cipher%20for%20Fast%20Encryption%20on%20Common%20Processors-English.pdf
|
|
||||||
* - https://ics.catswords.net/LEA-sourcecode-explanation.pdf
|
|
||||||
*
|
|
||||||
* license:
|
|
||||||
* GPLv3 or MS-RL(Microsoft Reciprocal License)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
using System;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace WelsonJS.Cryptography
|
|
||||||
{
|
|
||||||
public class LEA
|
|
||||||
{
|
|
||||||
private const int BLOCKSIZE = 16;
|
|
||||||
private static readonly uint[] delta = {
|
|
||||||
0xc3efe9db, 0x44626b02, 0x79e27c8a, 0x78df30ec,
|
|
||||||
0x715ea49e, 0xc785da0a, 0xe04ef22a, 0xe5c40957
|
|
||||||
};
|
|
||||||
|
|
||||||
private Mode mode;
|
|
||||||
private int rounds;
|
|
||||||
private uint[,] roundKeys;
|
|
||||||
private uint[] block;
|
|
||||||
|
|
||||||
public LEA()
|
|
||||||
{
|
|
||||||
block = new uint[BLOCKSIZE / 4];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init(Mode mode, byte[] mk)
|
|
||||||
{
|
|
||||||
this.mode = mode;
|
|
||||||
GenerateRoundKeys(mk);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset()
|
|
||||||
{
|
|
||||||
Array.Clear(block, 0, block.Length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetAlgorithmName()
|
|
||||||
{
|
|
||||||
return "LEA";
|
|
||||||
}
|
|
||||||
|
|
||||||
public int GetBlockSize()
|
|
||||||
{
|
|
||||||
return BLOCKSIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int ProcessBlock(byte[] input, int inputOffset, byte[] output, int outputOffset)
|
|
||||||
{
|
|
||||||
if (input == null || output == null)
|
|
||||||
throw new ArgumentNullException("Input and output buffers must not be null.");
|
|
||||||
|
|
||||||
if (input.Length - inputOffset < BLOCKSIZE)
|
|
||||||
throw new InvalidOperationException("Input data is too short.");
|
|
||||||
|
|
||||||
if (output.Length - outputOffset < BLOCKSIZE)
|
|
||||||
throw new InvalidOperationException("Output buffer is too short.");
|
|
||||||
|
|
||||||
return mode == Mode.ENCRYPT
|
|
||||||
? EncryptBlock(input, inputOffset, output, outputOffset)
|
|
||||||
: DecryptBlock(input, inputOffset, output, outputOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int EncryptBlock(byte[] input, int inputOffset, byte[] output, int outputOffset)
|
|
||||||
{
|
|
||||||
Pack(input, inputOffset, ref block, 0, 16);
|
|
||||||
|
|
||||||
for (int i = 0; i < rounds; ++i)
|
|
||||||
{
|
|
||||||
block[3] = ROR((block[2] ^ roundKeys[i, 4]) + (block[3] ^ roundKeys[i, 5]), 3);
|
|
||||||
block[2] = ROR((block[1] ^ roundKeys[i, 2]) + (block[2] ^ roundKeys[i, 3]), 5);
|
|
||||||
block[1] = ROL((block[0] ^ roundKeys[i, 0]) + (block[1] ^ roundKeys[i, 1]), 9);
|
|
||||||
++i;
|
|
||||||
|
|
||||||
block[0] = ROR((block[3] ^ roundKeys[i, 4]) + (block[0] ^ roundKeys[i, 5]), 3);
|
|
||||||
block[3] = ROR((block[2] ^ roundKeys[i, 2]) + (block[3] ^ roundKeys[i, 3]), 5);
|
|
||||||
block[2] = ROL((block[1] ^ roundKeys[i, 0]) + (block[2] ^ roundKeys[i, 1]), 9);
|
|
||||||
|
|
||||||
++i;
|
|
||||||
block[1] = ROR((block[0] ^ roundKeys[i, 4]) + (block[1] ^ roundKeys[i, 5]), 3);
|
|
||||||
block[0] = ROR((block[3] ^ roundKeys[i, 2]) + (block[0] ^ roundKeys[i, 3]), 5);
|
|
||||||
block[3] = ROL((block[2] ^ roundKeys[i, 0]) + (block[3] ^ roundKeys[i, 1]), 9);
|
|
||||||
|
|
||||||
++i;
|
|
||||||
block[2] = ROR((block[1] ^ roundKeys[i, 4]) + (block[2] ^ roundKeys[i, 5]), 3);
|
|
||||||
block[1] = ROR((block[0] ^ roundKeys[i, 2]) + (block[1] ^ roundKeys[i, 3]), 5);
|
|
||||||
block[0] = ROL((block[3] ^ roundKeys[i, 0]) + (block[0] ^ roundKeys[i, 1]), 9);
|
|
||||||
}
|
|
||||||
|
|
||||||
Unpack(block, 0, ref output, outputOffset, 4);
|
|
||||||
|
|
||||||
return BLOCKSIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int DecryptBlock(byte[] input, int inputOffset, byte[] output, int outputOffset)
|
|
||||||
{
|
|
||||||
Pack(input, inputOffset, ref block, 0, 16);
|
|
||||||
|
|
||||||
for (int i = rounds - 1; i >= 0; --i)
|
|
||||||
{
|
|
||||||
block[0] = (ROR(block[0], 9) - (block[3] ^ roundKeys[i, 0])) ^ roundKeys[i, 1];
|
|
||||||
block[1] = (ROL(block[1], 5) - (block[0] ^ roundKeys[i, 2])) ^ roundKeys[i, 3];
|
|
||||||
block[2] = (ROL(block[2], 3) - (block[1] ^ roundKeys[i, 4])) ^ roundKeys[i, 5];
|
|
||||||
--i;
|
|
||||||
|
|
||||||
block[3] = (ROR(block[3], 9) - (block[2] ^ roundKeys[i, 0])) ^ roundKeys[i, 1];
|
|
||||||
block[0] = (ROL(block[0], 5) - (block[3] ^ roundKeys[i, 2])) ^ roundKeys[i, 3];
|
|
||||||
block[1] = (ROL(block[1], 3) - (block[0] ^ roundKeys[i, 4])) ^ roundKeys[i, 5];
|
|
||||||
--i;
|
|
||||||
|
|
||||||
block[2] = (ROR(block[2], 9) - (block[1] ^ roundKeys[i, 0])) ^ roundKeys[i, 1];
|
|
||||||
block[3] = (ROL(block[3], 5) - (block[2] ^ roundKeys[i, 2])) ^ roundKeys[i, 3];
|
|
||||||
block[0] = (ROL(block[0], 3) - (block[3] ^ roundKeys[i, 4])) ^ roundKeys[i, 5];
|
|
||||||
--i;
|
|
||||||
|
|
||||||
block[1] = (ROR(block[1], 9) - (block[0] ^ roundKeys[i, 0])) ^ roundKeys[i, 1];
|
|
||||||
block[2] = (ROL(block[2], 5) - (block[1] ^ roundKeys[i, 2])) ^ roundKeys[i, 3];
|
|
||||||
block[3] = (ROL(block[3], 3) - (block[2] ^ roundKeys[i, 4])) ^ roundKeys[i, 5];
|
|
||||||
}
|
|
||||||
|
|
||||||
Unpack(block, 0, ref output, outputOffset, 4);
|
|
||||||
|
|
||||||
return BLOCKSIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GenerateRoundKeys(byte[] mk)
|
|
||||||
{
|
|
||||||
if (mk == null || (mk.Length != 16 && mk.Length != 24 && mk.Length != 32))
|
|
||||||
throw new ArgumentException("Illegal key size");
|
|
||||||
|
|
||||||
uint[] T = new uint[8];
|
|
||||||
rounds = (mk.Length >> 1) + 16;
|
|
||||||
roundKeys = new uint[rounds, 6];
|
|
||||||
|
|
||||||
Pack(mk, 0, ref T, 0, 16);
|
|
||||||
|
|
||||||
if (mk.Length > 16)
|
|
||||||
{
|
|
||||||
Pack(mk, 16, ref T, 4, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mk.Length > 24)
|
|
||||||
{
|
|
||||||
Pack(mk, 24, ref T, 6, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mk.Length == 16)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 24; ++i)
|
|
||||||
{
|
|
||||||
uint temp = ROL(delta[i & 3], i);
|
|
||||||
|
|
||||||
roundKeys[i, 0] = T[0] = ROL(T[0] + ROL(temp, 0), 1);
|
|
||||||
roundKeys[i, 1] = roundKeys[i, 3] = roundKeys[i, 5] = T[1] = ROL(T[1] + ROL(temp, 1), 3);
|
|
||||||
roundKeys[i, 2] = T[2] = ROL(T[2] + ROL(temp, 2), 6);
|
|
||||||
roundKeys[i, 4] = T[3] = ROL(T[3] + ROL(temp, 3), 11);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (mk.Length == 24)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 28; ++i)
|
|
||||||
{
|
|
||||||
uint temp = ROL(delta[i % 6], i);
|
|
||||||
|
|
||||||
roundKeys[i, 0] = T[0] = ROL(T[0] + ROL(temp, 0), 1);
|
|
||||||
roundKeys[i, 1] = T[1] = ROL(T[1] + ROL(temp, 1), 3);
|
|
||||||
roundKeys[i, 2] = T[2] = ROL(T[2] + ROL(temp, 2), 6);
|
|
||||||
roundKeys[i, 3] = T[3] = ROL(T[3] + ROL(temp, 3), 11);
|
|
||||||
roundKeys[i, 4] = T[4] = ROL(T[4] + ROL(temp, 4), 13);
|
|
||||||
roundKeys[i, 5] = T[5] = ROL(T[5] + ROL(temp, 5), 17);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 32; ++i)
|
|
||||||
{
|
|
||||||
uint temp = ROL(delta[i & 7], i & 0x1f);
|
|
||||||
|
|
||||||
roundKeys[i, 0] = T[(6 * i + 0) & 7] = ROL(T[(6 * i + 0) & 7] + temp, 1);
|
|
||||||
roundKeys[i, 1] = T[(6 * i + 1) & 7] = ROL(T[(6 * i + 1) & 7] + ROL(temp, 1), 3);
|
|
||||||
roundKeys[i, 2] = T[(6 * i + 2) & 7] = ROL(T[(6 * i + 2) & 7] + ROL(temp, 2), 6);
|
|
||||||
roundKeys[i, 3] = T[(6 * i + 3) & 7] = ROL(T[(6 * i + 3) & 7] + ROL(temp, 3), 11);
|
|
||||||
roundKeys[i, 4] = T[(6 * i + 4) & 7] = ROL(T[(6 * i + 4) & 7] + ROL(temp, 4), 13);
|
|
||||||
roundKeys[i, 5] = T[(6 * i + 5) & 7] = ROL(T[(6 * i + 5) & 7] + ROL(temp, 5), 17);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint ROL(uint state, int num)
|
|
||||||
{
|
|
||||||
return (state << num) | state >> (32 - num);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint ROR(uint state, int num)
|
|
||||||
{
|
|
||||||
return (state >> num) | state << (32 - num);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Pack(in byte[] input, int inputOffset, ref uint[] output, int outputOffset, int inputLength)
|
|
||||||
{
|
|
||||||
if (input == null || output == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((inputLength & 3) != 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Length should be a multiple of 4.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input.Length < inputOffset + inputLength || output.Length < outputOffset + inputLength / 4)
|
|
||||||
{
|
|
||||||
throw new IndexOutOfRangeException();
|
|
||||||
}
|
|
||||||
|
|
||||||
int outputIndex = 0;
|
|
||||||
for (int inputIdx = 0; inputIdx < input.Length; ++inputIdx, ++outputIndex) {
|
|
||||||
output[outputIndex] = (uint)(input[inputIdx] & 0xff);
|
|
||||||
output[outputIndex] |= (uint)((input[++inputIdx] & 0xff) << 8);
|
|
||||||
output[outputIndex] |= (uint)((input[++inputIdx] & 0xff) << 16);
|
|
||||||
output[outputIndex] |= (uint)((input[++inputIdx] & 0xff) << 24);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Unpack(in uint[] input, int inputOffset, ref byte[] output, int outputOffset, int inputLength)
|
|
||||||
{
|
|
||||||
if (input == null || output == null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input.Length < inputOffset + inputLength || output.Length < outputOffset + inputLength * 4)
|
|
||||||
{
|
|
||||||
throw new IndexOutOfRangeException();
|
|
||||||
}
|
|
||||||
|
|
||||||
int outputIdx = outputOffset;
|
|
||||||
int endInIdx = inputOffset + inputLength;
|
|
||||||
for (int inputIdx = inputOffset; inputIdx < endInIdx; ++inputIdx, ++outputIdx)
|
|
||||||
{
|
|
||||||
output[outputIdx] = (byte)input[inputIdx] ;
|
|
||||||
output[++outputIdx] = (byte)(input[inputIdx] >> 8);
|
|
||||||
output[++outputIdx] = (byte)(input[inputIdx] >> 16);
|
|
||||||
output[++outputIdx] = (byte)(input[inputIdx] >> 24);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Mode
|
|
||||||
{
|
|
||||||
ENCRYPT,
|
|
||||||
DECRYPT
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ECB
|
|
||||||
{
|
|
||||||
private Mode mode;
|
|
||||||
private LEA engine;
|
|
||||||
private int blockSize;
|
|
||||||
|
|
||||||
ECB(Mode mode, string key)
|
|
||||||
{
|
|
||||||
engine = new LEA();
|
|
||||||
Init(mode, CreateKey(key));
|
|
||||||
blockSize = engine.GetBlockSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetAlgorithmName()
|
|
||||||
{
|
|
||||||
return engine.GetAlgorithmName() + "/ECB";
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init(Mode mode, byte[] mk)
|
|
||||||
{
|
|
||||||
this.mode = mode;
|
|
||||||
engine.Init(mode, mk);
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] CreateKey(string key)
|
|
||||||
{
|
|
||||||
SHA256 hasher = SHA256.Create();
|
|
||||||
byte[] hashData = hasher.ComputeHash(Encoding.Default.GetBytes(key));
|
|
||||||
|
|
||||||
return hashData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] Encrypt(byte[] data)
|
|
||||||
{
|
|
||||||
if (this.mode != Mode.ENCRYPT)
|
|
||||||
throw new InvalidOperationException("Not initialized for encryption mode.");
|
|
||||||
|
|
||||||
byte[] inputData = PKCS5Padding.AddPadding(data, blockSize);
|
|
||||||
byte[] outputData = new byte[inputData.Length];
|
|
||||||
|
|
||||||
for (int i = 0; i < inputData.Length; i += blockSize)
|
|
||||||
{
|
|
||||||
engine.ProcessBlock(inputData, i, outputData, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return outputData;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] Decrypt(byte[] data)
|
|
||||||
{
|
|
||||||
if (this.mode != Mode.DECRYPT)
|
|
||||||
throw new InvalidOperationException("Not initialized for decryption mode.");
|
|
||||||
|
|
||||||
byte[] outputData = new byte[data.Length];
|
|
||||||
|
|
||||||
for (int i = 0; i < data.Length; i += blockSize)
|
|
||||||
{
|
|
||||||
engine.ProcessBlock(data, i, outputData, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return PKCS5Padding.RemovePadding(outputData, blockSize, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,118 +0,0 @@
|
||||||
/*
|
|
||||||
* WelsonJS.Toolkit: WelsonJS native component
|
|
||||||
*
|
|
||||||
* filename:
|
|
||||||
* PKCS5Padding.cs
|
|
||||||
*
|
|
||||||
* description:
|
|
||||||
* PKCS5Padding implementation
|
|
||||||
*
|
|
||||||
* website:
|
|
||||||
* - https://github.com/gnh1201/welsonjs
|
|
||||||
* - https://catswords.social/@catswords_oss
|
|
||||||
* - https://teams.live.com/l/community/FEACHncAhq8ldnojAI
|
|
||||||
* - https://discord.gg/XKG5CjtXEj
|
|
||||||
*
|
|
||||||
* authors:
|
|
||||||
* - Namhyeon Go (@gnh1201) <abuse@catswords.net>
|
|
||||||
*
|
|
||||||
* references:
|
|
||||||
* - ChatGPT prompt "PKCS5Padding with C#" (chatgpt.com)
|
|
||||||
* - ChatGPT prompt "PKCS5Padding with C#, Add a flag to decide how to handle possible errors when removing padding." (chatgpt.com)
|
|
||||||
*
|
|
||||||
* license:
|
|
||||||
* GPLv3 or MS-RL(Microsoft Reciprocal License)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace WelsonJS.Cryptography
|
|
||||||
{
|
|
||||||
public class PKCS5Padding
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Add PKCS#5 padding to the input data to make it a multiple of the block size.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="data">The data to be padded.</param>
|
|
||||||
/// <param name="blockSize">The block size to pad to.</param>
|
|
||||||
/// <returns>Padded data with PKCS#5 padding.</returns>
|
|
||||||
public static byte[] AddPadding(byte[] data, int blockSize)
|
|
||||||
{
|
|
||||||
int paddingLength = blockSize - (data.Length % blockSize);
|
|
||||||
|
|
||||||
// If the data is already a multiple of the block size, no padding is needed
|
|
||||||
if (paddingLength == blockSize)
|
|
||||||
{
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] paddedData = new byte[data.Length + paddingLength];
|
|
||||||
|
|
||||||
// Copy original data into the padded array
|
|
||||||
Array.Copy(data, paddedData, data.Length);
|
|
||||||
|
|
||||||
// Fill padding with the padding length (PKCS5)
|
|
||||||
for (int i = data.Length; i < paddedData.Length; i++)
|
|
||||||
{
|
|
||||||
paddedData[i] = (byte)paddingLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
return paddedData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes PKCS#5 padding from the given data.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="data">The input data, including padding.</param>
|
|
||||||
/// <param name="blockSize">The block size used for padding.</param>
|
|
||||||
/// <param name="ignoreErrors">If true, ignores errors and attempts to process the input data as-is.</param>
|
|
||||||
/// <returns>The unpadded data as a byte array.</returns>
|
|
||||||
/// <exception cref="ArgumentException">Thrown if the input data or padding is invalid and ignoreErrors is false.</exception>
|
|
||||||
public static byte[] RemovePadding(byte[] data, int blockSize, bool ignoreErrors = false)
|
|
||||||
{
|
|
||||||
// If data length is 0, return empty array
|
|
||||||
if (data.Length == 0)
|
|
||||||
{
|
|
||||||
return new byte[] { };
|
|
||||||
}
|
|
||||||
|
|
||||||
// If data length is smaller than block size, treat it as unpadded
|
|
||||||
if (data.Length < blockSize)
|
|
||||||
{
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the last byte is valid padding (PKCS5)
|
|
||||||
int paddingLength = data[data.Length - 1];
|
|
||||||
|
|
||||||
// Validate padding length
|
|
||||||
if (paddingLength <= 0 || paddingLength > blockSize)
|
|
||||||
{
|
|
||||||
if (!ignoreErrors)
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"Invalid padding length: {paddingLength}. Must be between 1 and {blockSize}.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the padding is correct (i.e., all padding bytes must be equal to paddingLength)
|
|
||||||
for (int i = data.Length - paddingLength; i < data.Length; i++)
|
|
||||||
{
|
|
||||||
if (data[i] != paddingLength)
|
|
||||||
{
|
|
||||||
if (!ignoreErrors)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Invalid padding detected.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the padding
|
|
||||||
byte[] unpaddedData = new byte[data.Length - paddingLength];
|
|
||||||
Array.Copy(data, unpaddedData, unpaddedData.Length);
|
|
||||||
|
|
||||||
return unpaddedData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,755 +0,0 @@
|
||||||
/*
|
|
||||||
* WelsonJS.Toolkit: WelsonJS native component
|
|
||||||
*
|
|
||||||
* filename:
|
|
||||||
* SEED.cs
|
|
||||||
*
|
|
||||||
* description:
|
|
||||||
* SEED(ISO/IEC 18033-3) cryptography algorithm implementation (Experimental)
|
|
||||||
*
|
|
||||||
* website:
|
|
||||||
* - https://github.com/gnh1201/welsonjs
|
|
||||||
* - https://catswords.social/@catswords_oss
|
|
||||||
* - https://teams.live.com/l/community/FEACHncAhq8ldnojAI
|
|
||||||
* - https://discord.gg/XKG5CjtXEj
|
|
||||||
*
|
|
||||||
* author:
|
|
||||||
* - Namhyeon Go (@gnh1201) <abuse@catswords.net>
|
|
||||||
* - KISA(Korea Internet & Security Agency) (kisa.or.kr)
|
|
||||||
*
|
|
||||||
* references:
|
|
||||||
* - https://seed.kisa.or.kr/kisa/Board/17/detailView.do
|
|
||||||
* - https://www.iso.org/standard/54531.html
|
|
||||||
* - https://ics.catswords.net/SEED%2B128_Specification_english_M.pdf
|
|
||||||
* - https://ics.catswords.net/SEED_Algorithm_Specification_korean_M.pdf
|
|
||||||
* - https://ics.catswords.net/SEED_sourcecode_explanation_korean.pdf
|
|
||||||
*
|
|
||||||
* license:
|
|
||||||
* GPLv3 or MS-RL(Microsoft Reciprocal License)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace WelsonJS.Cryptography
|
|
||||||
{
|
|
||||||
public class SEED
|
|
||||||
{
|
|
||||||
public enum ENDIAN {
|
|
||||||
BIG,
|
|
||||||
LITTLE
|
|
||||||
};
|
|
||||||
private static ENDIAN DEFAULT_ENDIAN = ENDIAN.BIG;
|
|
||||||
|
|
||||||
// Constants for Key schedule
|
|
||||||
private const uint KC0 = 0x9e3779b9;
|
|
||||||
private const uint KC1 = 0x3c6ef373;
|
|
||||||
private const uint KC2 = 0x78dde6e6;
|
|
||||||
private const uint KC3 = 0xf1bbcdcc;
|
|
||||||
private const uint KC4 = 0xe3779b99;
|
|
||||||
private const uint KC5 = 0xc6ef3733;
|
|
||||||
private const uint KC6 = 0x8dde6e67;
|
|
||||||
private const uint KC7 = 0x1bbcdccf;
|
|
||||||
private const uint KC8 = 0x3779b99e;
|
|
||||||
private const uint KC9 = 0x6ef3733c;
|
|
||||||
private const uint KC10 = 0xdde6e678;
|
|
||||||
private const uint KC11 = 0xbbcdccf1;
|
|
||||||
private const uint KC12 = 0x779b99e3;
|
|
||||||
private const uint KC13 = 0xef3733c6;
|
|
||||||
private const uint KC14 = 0xde6e678d;
|
|
||||||
private const uint KC15 = 0xbcdccf1b;
|
|
||||||
|
|
||||||
private const int ABCD_A = 0;
|
|
||||||
private const int ABCD_B = 1;
|
|
||||||
private const int ABCD_C = 2;
|
|
||||||
private const int ABCD_D = 3;
|
|
||||||
|
|
||||||
private const int LR_L0 = 0;
|
|
||||||
private const int LR_L1 = 1;
|
|
||||||
private const int LR_R0 = 2;
|
|
||||||
private const int LR_R1 = 3;
|
|
||||||
|
|
||||||
private const int BLOCK_SIZE_SEED = 16;
|
|
||||||
private const int BLOCK_SIZE_SEED_INT = 4;
|
|
||||||
|
|
||||||
// S-BOX
|
|
||||||
private static readonly uint[] SS0 = new uint[] {
|
|
||||||
0x2989a1a8, 0x05858184, 0x16c6d2d4, 0x13c3d3d0, 0x14445054, 0x1d0d111c, 0x2c8ca0ac, 0x25052124,
|
|
||||||
0x1d4d515c, 0x03434340, 0x18081018, 0x1e0e121c, 0x11415150, 0x3cccf0fc, 0x0acac2c8, 0x23436360,
|
|
||||||
0x28082028, 0x04444044, 0x20002020, 0x1d8d919c, 0x20c0e0e0, 0x22c2e2e0, 0x08c8c0c8, 0x17071314,
|
|
||||||
0x2585a1a4, 0x0f8f838c, 0x03030300, 0x3b4b7378, 0x3b8bb3b8, 0x13031310, 0x12c2d2d0, 0x2ecee2ec,
|
|
||||||
0x30407070, 0x0c8c808c, 0x3f0f333c, 0x2888a0a8, 0x32023230, 0x1dcdd1dc, 0x36c6f2f4, 0x34447074,
|
|
||||||
0x2ccce0ec, 0x15859194, 0x0b0b0308, 0x17475354, 0x1c4c505c, 0x1b4b5358, 0x3d8db1bc, 0x01010100,
|
|
||||||
0x24042024, 0x1c0c101c, 0x33437370, 0x18889098, 0x10001010, 0x0cccc0cc, 0x32c2f2f0, 0x19c9d1d8,
|
|
||||||
0x2c0c202c, 0x27c7e3e4, 0x32427270, 0x03838380, 0x1b8b9398, 0x11c1d1d0, 0x06868284, 0x09c9c1c8,
|
|
||||||
0x20406060, 0x10405050, 0x2383a3a0, 0x2bcbe3e8, 0x0d0d010c, 0x3686b2b4, 0x1e8e929c, 0x0f4f434c,
|
|
||||||
0x3787b3b4, 0x1a4a5258, 0x06c6c2c4, 0x38487078, 0x2686a2a4, 0x12021210, 0x2f8fa3ac, 0x15c5d1d4,
|
|
||||||
0x21416160, 0x03c3c3c0, 0x3484b0b4, 0x01414140, 0x12425250, 0x3d4d717c, 0x0d8d818c, 0x08080008,
|
|
||||||
0x1f0f131c, 0x19899198, 0x00000000, 0x19091118, 0x04040004, 0x13435350, 0x37c7f3f4, 0x21c1e1e0,
|
|
||||||
0x3dcdf1fc, 0x36467274, 0x2f0f232c, 0x27072324, 0x3080b0b0, 0x0b8b8388, 0x0e0e020c, 0x2b8ba3a8,
|
|
||||||
0x2282a2a0, 0x2e4e626c, 0x13839390, 0x0d4d414c, 0x29496168, 0x3c4c707c, 0x09090108, 0x0a0a0208,
|
|
||||||
0x3f8fb3bc, 0x2fcfe3ec, 0x33c3f3f0, 0x05c5c1c4, 0x07878384, 0x14041014, 0x3ecef2fc, 0x24446064,
|
|
||||||
0x1eced2dc, 0x2e0e222c, 0x0b4b4348, 0x1a0a1218, 0x06060204, 0x21012120, 0x2b4b6368, 0x26466264,
|
|
||||||
0x02020200, 0x35c5f1f4, 0x12829290, 0x0a8a8288, 0x0c0c000c, 0x3383b3b0, 0x3e4e727c, 0x10c0d0d0,
|
|
||||||
0x3a4a7278, 0x07474344, 0x16869294, 0x25c5e1e4, 0x26062224, 0x00808080, 0x2d8da1ac, 0x1fcfd3dc,
|
|
||||||
0x2181a1a0, 0x30003030, 0x37073334, 0x2e8ea2ac, 0x36063234, 0x15051114, 0x22022220, 0x38083038,
|
|
||||||
0x34c4f0f4, 0x2787a3a4, 0x05454144, 0x0c4c404c, 0x01818180, 0x29c9e1e8, 0x04848084, 0x17879394,
|
|
||||||
0x35053134, 0x0bcbc3c8, 0x0ecec2cc, 0x3c0c303c, 0x31417170, 0x11011110, 0x07c7c3c4, 0x09898188,
|
|
||||||
0x35457174, 0x3bcbf3f8, 0x1acad2d8, 0x38c8f0f8, 0x14849094, 0x19495158, 0x02828280, 0x04c4c0c4,
|
|
||||||
0x3fcff3fc, 0x09494148, 0x39093138, 0x27476364, 0x00c0c0c0, 0x0fcfc3cc, 0x17c7d3d4, 0x3888b0b8,
|
|
||||||
0x0f0f030c, 0x0e8e828c, 0x02424240, 0x23032320, 0x11819190, 0x2c4c606c, 0x1bcbd3d8, 0x2484a0a4,
|
|
||||||
0x34043034, 0x31c1f1f0, 0x08484048, 0x02c2c2c0, 0x2f4f636c, 0x3d0d313c, 0x2d0d212c, 0x00404040,
|
|
||||||
0x3e8eb2bc, 0x3e0e323c, 0x3c8cb0bc, 0x01c1c1c0, 0x2a8aa2a8, 0x3a8ab2b8, 0x0e4e424c, 0x15455154,
|
|
||||||
0x3b0b3338, 0x1cccd0dc, 0x28486068, 0x3f4f737c, 0x1c8c909c, 0x18c8d0d8, 0x0a4a4248, 0x16465254,
|
|
||||||
0x37477374, 0x2080a0a0, 0x2dcde1ec, 0x06464244, 0x3585b1b4, 0x2b0b2328, 0x25456164, 0x3acaf2f8,
|
|
||||||
0x23c3e3e0, 0x3989b1b8, 0x3181b1b0, 0x1f8f939c, 0x1e4e525c, 0x39c9f1f8, 0x26c6e2e4, 0x3282b2b0,
|
|
||||||
0x31013130, 0x2acae2e8, 0x2d4d616c, 0x1f4f535c, 0x24c4e0e4, 0x30c0f0f0, 0x0dcdc1cc, 0x08888088,
|
|
||||||
0x16061214, 0x3a0a3238, 0x18485058, 0x14c4d0d4, 0x22426260, 0x29092128, 0x07070304, 0x33033330,
|
|
||||||
0x28c8e0e8, 0x1b0b1318, 0x05050104, 0x39497178, 0x10809090, 0x2a4a6268, 0x2a0a2228, 0x1a8a9298
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly uint[] SS1 = new uint[]
|
|
||||||
{
|
|
||||||
0x38380830, 0xe828c8e0, 0x2c2d0d21, 0xa42686a2, 0xcc0fcfc3, 0xdc1eced2, 0xb03383b3, 0xb83888b0,
|
|
||||||
0xac2f8fa3, 0x60204060, 0x54154551, 0xc407c7c3, 0x44044440, 0x6c2f4f63, 0x682b4b63, 0x581b4b53,
|
|
||||||
0xc003c3c3, 0x60224262, 0x30330333, 0xb43585b1, 0x28290921, 0xa02080a0, 0xe022c2e2, 0xa42787a3,
|
|
||||||
0xd013c3d3, 0x90118191, 0x10110111, 0x04060602, 0x1c1c0c10, 0xbc3c8cb0, 0x34360632, 0x480b4b43,
|
|
||||||
0xec2fcfe3, 0x88088880, 0x6c2c4c60, 0xa82888a0, 0x14170713, 0xc404c4c0, 0x14160612, 0xf434c4f0,
|
|
||||||
0xc002c2c2, 0x44054541, 0xe021c1e1, 0xd416c6d2, 0x3c3f0f33, 0x3c3d0d31, 0x8c0e8e82, 0x98188890,
|
|
||||||
0x28280820, 0x4c0e4e42, 0xf436c6f2, 0x3c3e0e32, 0xa42585a1, 0xf839c9f1, 0x0c0d0d01, 0xdc1fcfd3,
|
|
||||||
0xd818c8d0, 0x282b0b23, 0x64264662, 0x783a4a72, 0x24270723, 0x2c2f0f23, 0xf031c1f1, 0x70324272,
|
|
||||||
0x40024242, 0xd414c4d0, 0x40014141, 0xc000c0c0, 0x70334373, 0x64274763, 0xac2c8ca0, 0x880b8b83,
|
|
||||||
0xf437c7f3, 0xac2d8da1, 0x80008080, 0x1c1f0f13, 0xc80acac2, 0x2c2c0c20, 0xa82a8aa2, 0x34340430,
|
|
||||||
0xd012c2d2, 0x080b0b03, 0xec2ecee2, 0xe829c9e1, 0x5c1d4d51, 0x94148490, 0x18180810, 0xf838c8f0,
|
|
||||||
0x54174753, 0xac2e8ea2, 0x08080800, 0xc405c5c1, 0x10130313, 0xcc0dcdc1, 0x84068682, 0xb83989b1,
|
|
||||||
0xfc3fcff3, 0x7c3d4d71, 0xc001c1c1, 0x30310131, 0xf435c5f1, 0x880a8a82, 0x682a4a62, 0xb03181b1,
|
|
||||||
0xd011c1d1, 0x20200020, 0xd417c7d3, 0x00020202, 0x20220222, 0x04040400, 0x68284860, 0x70314171,
|
|
||||||
0x04070703, 0xd81bcbd3, 0x9c1d8d91, 0x98198991, 0x60214161, 0xbc3e8eb2, 0xe426c6e2, 0x58194951,
|
|
||||||
0xdc1dcdd1, 0x50114151, 0x90108090, 0xdc1cccd0, 0x981a8a92, 0xa02383a3, 0xa82b8ba3, 0xd010c0d0,
|
|
||||||
0x80018181, 0x0c0f0f03, 0x44074743, 0x181a0a12, 0xe023c3e3, 0xec2ccce0, 0x8c0d8d81, 0xbc3f8fb3,
|
|
||||||
0x94168692, 0x783b4b73, 0x5c1c4c50, 0xa02282a2, 0xa02181a1, 0x60234363, 0x20230323, 0x4c0d4d41,
|
|
||||||
0xc808c8c0, 0x9c1e8e92, 0x9c1c8c90, 0x383a0a32, 0x0c0c0c00, 0x2c2e0e22, 0xb83a8ab2, 0x6c2e4e62,
|
|
||||||
0x9c1f8f93, 0x581a4a52, 0xf032c2f2, 0x90128292, 0xf033c3f3, 0x48094941, 0x78384870, 0xcc0cccc0,
|
|
||||||
0x14150511, 0xf83bcbf3, 0x70304070, 0x74354571, 0x7c3f4f73, 0x34350531, 0x10100010, 0x00030303,
|
|
||||||
0x64244460, 0x6c2d4d61, 0xc406c6c2, 0x74344470, 0xd415c5d1, 0xb43484b0, 0xe82acae2, 0x08090901,
|
|
||||||
0x74364672, 0x18190911, 0xfc3ecef2, 0x40004040, 0x10120212, 0xe020c0e0, 0xbc3d8db1, 0x04050501,
|
|
||||||
0xf83acaf2, 0x00010101, 0xf030c0f0, 0x282a0a22, 0x5c1e4e52, 0xa82989a1, 0x54164652, 0x40034343,
|
|
||||||
0x84058581, 0x14140410, 0x88098981, 0x981b8b93, 0xb03080b0, 0xe425c5e1, 0x48084840, 0x78394971,
|
|
||||||
0x94178793, 0xfc3cccf0, 0x1c1e0e12, 0x80028282, 0x20210121, 0x8c0c8c80, 0x181b0b13, 0x5c1f4f53,
|
|
||||||
0x74374773, 0x54144450, 0xb03282b2, 0x1c1d0d11, 0x24250521, 0x4c0f4f43, 0x00000000, 0x44064642,
|
|
||||||
0xec2dcde1, 0x58184850, 0x50124252, 0xe82bcbe3, 0x7c3e4e72, 0xd81acad2, 0xc809c9c1, 0xfc3dcdf1,
|
|
||||||
0x30300030, 0x94158591, 0x64254561, 0x3c3c0c30, 0xb43686b2, 0xe424c4e0, 0xb83b8bb3, 0x7c3c4c70,
|
|
||||||
0x0c0e0e02, 0x50104050, 0x38390931, 0x24260622, 0x30320232, 0x84048480, 0x68294961, 0x90138393,
|
|
||||||
0x34370733, 0xe427c7e3, 0x24240420, 0xa42484a0, 0xc80bcbc3, 0x50134353, 0x080a0a02, 0x84078783,
|
|
||||||
0xd819c9d1, 0x4c0c4c40, 0x80038383, 0x8c0f8f83, 0xcc0ecec2, 0x383b0b33, 0x480a4a42, 0xb43787b3
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly uint[] SS2 = new uint[]
|
|
||||||
{
|
|
||||||
0xa1a82989, 0x81840585, 0xd2d416c6, 0xd3d013c3, 0x50541444, 0x111c1d0d, 0xa0ac2c8c, 0x21242505,
|
|
||||||
0x515c1d4d, 0x43400343, 0x10181808, 0x121c1e0e, 0x51501141, 0xf0fc3ccc, 0xc2c80aca, 0x63602343,
|
|
||||||
0x20282808, 0x40440444, 0x20202000, 0x919c1d8d, 0xe0e020c0, 0xe2e022c2, 0xc0c808c8, 0x13141707,
|
|
||||||
0xa1a42585, 0x838c0f8f, 0x03000303, 0x73783b4b, 0xb3b83b8b, 0x13101303, 0xd2d012c2, 0xe2ec2ece,
|
|
||||||
0x70703040, 0x808c0c8c, 0x333c3f0f, 0xa0a82888, 0x32303202, 0xd1dc1dcd, 0xf2f436c6, 0x70743444,
|
|
||||||
0xe0ec2ccc, 0x91941585, 0x03080b0b, 0x53541747, 0x505c1c4c, 0x53581b4b, 0xb1bc3d8d, 0x01000101,
|
|
||||||
0x20242404, 0x101c1c0c, 0x73703343, 0x90981888, 0x10101000, 0xc0cc0ccc, 0xf2f032c2, 0xd1d819c9,
|
|
||||||
0x202c2c0c, 0xe3e427c7, 0x72703242, 0x83800383, 0x93981b8b, 0xd1d011c1, 0x82840686, 0xc1c809c9,
|
|
||||||
0x60602040, 0x50501040, 0xa3a02383, 0xe3e82bcb, 0x010c0d0d, 0xb2b43686, 0x929c1e8e, 0x434c0f4f,
|
|
||||||
0xb3b43787, 0x52581a4a, 0xc2c406c6, 0x70783848, 0xa2a42686, 0x12101202, 0xa3ac2f8f, 0xd1d415c5,
|
|
||||||
0x61602141, 0xc3c003c3, 0xb0b43484, 0x41400141, 0x52501242, 0x717c3d4d, 0x818c0d8d, 0x00080808,
|
|
||||||
0x131c1f0f, 0x91981989, 0x00000000, 0x11181909, 0x00040404, 0x53501343, 0xf3f437c7, 0xe1e021c1,
|
|
||||||
0xf1fc3dcd, 0x72743646, 0x232c2f0f, 0x23242707, 0xb0b03080, 0x83880b8b, 0x020c0e0e, 0xa3a82b8b,
|
|
||||||
0xa2a02282, 0x626c2e4e, 0x93901383, 0x414c0d4d, 0x61682949, 0x707c3c4c, 0x01080909, 0x02080a0a,
|
|
||||||
0xb3bc3f8f, 0xe3ec2fcf, 0xf3f033c3, 0xc1c405c5, 0x83840787, 0x10141404, 0xf2fc3ece, 0x60642444,
|
|
||||||
0xd2dc1ece, 0x222c2e0e, 0x43480b4b, 0x12181a0a, 0x02040606, 0x21202101, 0x63682b4b, 0x62642646,
|
|
||||||
0x02000202, 0xf1f435c5, 0x92901282, 0x82880a8a, 0x000c0c0c, 0xb3b03383, 0x727c3e4e, 0xd0d010c0,
|
|
||||||
0x72783a4a, 0x43440747, 0x92941686, 0xe1e425c5, 0x22242606, 0x80800080, 0xa1ac2d8d, 0xd3dc1fcf,
|
|
||||||
0xa1a02181, 0x30303000, 0x33343707, 0xa2ac2e8e, 0x32343606, 0x11141505, 0x22202202, 0x30383808,
|
|
||||||
0xf0f434c4, 0xa3a42787, 0x41440545, 0x404c0c4c, 0x81800181, 0xe1e829c9, 0x80840484, 0x93941787,
|
|
||||||
0x31343505, 0xc3c80bcb, 0xc2cc0ece, 0x303c3c0c, 0x71703141, 0x11101101, 0xc3c407c7, 0x81880989,
|
|
||||||
0x71743545, 0xf3f83bcb, 0xd2d81aca, 0xf0f838c8, 0x90941484, 0x51581949, 0x82800282, 0xc0c404c4,
|
|
||||||
0xf3fc3fcf, 0x41480949, 0x31383909, 0x63642747, 0xc0c000c0, 0xc3cc0fcf, 0xd3d417c7, 0xb0b83888,
|
|
||||||
0x030c0f0f, 0x828c0e8e, 0x42400242, 0x23202303, 0x91901181, 0x606c2c4c, 0xd3d81bcb, 0xa0a42484,
|
|
||||||
0x30343404, 0xf1f031c1, 0x40480848, 0xc2c002c2, 0x636c2f4f, 0x313c3d0d, 0x212c2d0d, 0x40400040,
|
|
||||||
0xb2bc3e8e, 0x323c3e0e, 0xb0bc3c8c, 0xc1c001c1, 0xa2a82a8a, 0xb2b83a8a, 0x424c0e4e, 0x51541545,
|
|
||||||
0x33383b0b, 0xd0dc1ccc, 0x60682848, 0x737c3f4f, 0x909c1c8c, 0xd0d818c8, 0x42480a4a, 0x52541646,
|
|
||||||
0x73743747, 0xa0a02080, 0xe1ec2dcd, 0x42440646, 0xb1b43585, 0x23282b0b, 0x61642545, 0xf2f83aca,
|
|
||||||
0xe3e023c3, 0xb1b83989, 0xb1b03181, 0x939c1f8f, 0x525c1e4e, 0xf1f839c9, 0xe2e426c6, 0xb2b03282,
|
|
||||||
0x31303101, 0xe2e82aca, 0x616c2d4d, 0x535c1f4f, 0xe0e424c4, 0xf0f030c0, 0xc1cc0dcd, 0x80880888,
|
|
||||||
0x12141606, 0x32383a0a, 0x50581848, 0xd0d414c4, 0x62602242, 0x21282909, 0x03040707, 0x33303303,
|
|
||||||
0xe0e828c8, 0x13181b0b, 0x01040505, 0x71783949, 0x90901080, 0x62682a4a, 0x22282a0a, 0x92981a8a
|
|
||||||
};
|
|
||||||
|
|
||||||
private static uint[] SS3 = new uint[]
|
|
||||||
{
|
|
||||||
0x08303838, 0xc8e0e828, 0x0d212c2d, 0x86a2a426, 0xcfc3cc0f, 0xced2dc1e, 0x83b3b033, 0x88b0b838,
|
|
||||||
0x8fa3ac2f, 0x40606020, 0x45515415, 0xc7c3c407, 0x44404404, 0x4f636c2f, 0x4b63682b, 0x4b53581b,
|
|
||||||
0xc3c3c003, 0x42626022, 0x03333033, 0x85b1b435, 0x09212829, 0x80a0a020, 0xc2e2e022, 0x87a3a427,
|
|
||||||
0xc3d3d013, 0x81919011, 0x01111011, 0x06020406, 0x0c101c1c, 0x8cb0bc3c, 0x06323436, 0x4b43480b,
|
|
||||||
0xcfe3ec2f, 0x88808808, 0x4c606c2c, 0x88a0a828, 0x07131417, 0xc4c0c404, 0x06121416, 0xc4f0f434,
|
|
||||||
0xc2c2c002, 0x45414405, 0xc1e1e021, 0xc6d2d416, 0x0f333c3f, 0x0d313c3d, 0x8e828c0e, 0x88909818,
|
|
||||||
0x08202828, 0x4e424c0e, 0xc6f2f436, 0x0e323c3e, 0x85a1a425, 0xc9f1f839, 0x0d010c0d, 0xcfd3dc1f,
|
|
||||||
0xc8d0d818, 0x0b23282b, 0x46626426, 0x4a72783a, 0x07232427, 0x0f232c2f, 0xc1f1f031, 0x42727032,
|
|
||||||
0x42424002, 0xc4d0d414, 0x41414001, 0xc0c0c000, 0x43737033, 0x47636427, 0x8ca0ac2c, 0x8b83880b,
|
|
||||||
0xc7f3f437, 0x8da1ac2d, 0x80808000, 0x0f131c1f, 0xcac2c80a, 0x0c202c2c, 0x8aa2a82a, 0x04303434,
|
|
||||||
0xc2d2d012, 0x0b03080b, 0xcee2ec2e, 0xc9e1e829, 0x4d515c1d, 0x84909414, 0x08101818, 0xc8f0f838,
|
|
||||||
0x47535417, 0x8ea2ac2e, 0x08000808, 0xc5c1c405, 0x03131013, 0xcdc1cc0d, 0x86828406, 0x89b1b839,
|
|
||||||
0xcff3fc3f, 0x4d717c3d, 0xc1c1c001, 0x01313031, 0xc5f1f435, 0x8a82880a, 0x4a62682a, 0x81b1b031,
|
|
||||||
0xc1d1d011, 0x00202020, 0xc7d3d417, 0x02020002, 0x02222022, 0x04000404, 0x48606828, 0x41717031,
|
|
||||||
0x07030407, 0xcbd3d81b, 0x8d919c1d, 0x89919819, 0x41616021, 0x8eb2bc3e, 0xc6e2e426, 0x49515819,
|
|
||||||
0xcdd1dc1d, 0x41515011, 0x80909010, 0xccd0dc1c, 0x8a92981a, 0x83a3a023, 0x8ba3a82b, 0xc0d0d010,
|
|
||||||
0x81818001, 0x0f030c0f, 0x47434407, 0x0a12181a, 0xc3e3e023, 0xcce0ec2c, 0x8d818c0d, 0x8fb3bc3f,
|
|
||||||
0x86929416, 0x4b73783b, 0x4c505c1c, 0x82a2a022, 0x81a1a021, 0x43636023, 0x03232023, 0x4d414c0d,
|
|
||||||
0xc8c0c808, 0x8e929c1e, 0x8c909c1c, 0x0a32383a, 0x0c000c0c, 0x0e222c2e, 0x8ab2b83a, 0x4e626c2e,
|
|
||||||
0x8f939c1f, 0x4a52581a, 0xc2f2f032, 0x82929012, 0xc3f3f033, 0x49414809, 0x48707838, 0xccc0cc0c,
|
|
||||||
0x05111415, 0xcbf3f83b, 0x40707030, 0x45717435, 0x4f737c3f, 0x05313435, 0x00101010, 0x03030003,
|
|
||||||
0x44606424, 0x4d616c2d, 0xc6c2c406, 0x44707434, 0xc5d1d415, 0x84b0b434, 0xcae2e82a, 0x09010809,
|
|
||||||
0x46727436, 0x09111819, 0xcef2fc3e, 0x40404000, 0x02121012, 0xc0e0e020, 0x8db1bc3d, 0x05010405,
|
|
||||||
0xcaf2f83a, 0x01010001, 0xc0f0f030, 0x0a22282a, 0x4e525c1e, 0x89a1a829, 0x46525416, 0x43434003,
|
|
||||||
0x85818405, 0x04101414, 0x89818809, 0x8b93981b, 0x80b0b030, 0xc5e1e425, 0x48404808, 0x49717839,
|
|
||||||
0x87939417, 0xccf0fc3c, 0x0e121c1e, 0x82828002, 0x01212021, 0x8c808c0c, 0x0b13181b, 0x4f535c1f,
|
|
||||||
0x47737437, 0x44505414, 0x82b2b032, 0x0d111c1d, 0x05212425, 0x4f434c0f, 0x00000000, 0x46424406,
|
|
||||||
0xcde1ec2d, 0x48505818, 0x42525012, 0xcbe3e82b, 0x4e727c3e, 0xcad2d81a, 0xc9c1c809, 0xcdf1fc3d,
|
|
||||||
0x00303030, 0x85919415, 0x45616425, 0x0c303c3c, 0x86b2b436, 0xc4e0e424, 0x8bb3b83b, 0x4c707c3c,
|
|
||||||
0x0e020c0e, 0x40505010, 0x09313839, 0x06222426, 0x02323032, 0x84808404, 0x49616829, 0x83939013,
|
|
||||||
0x07333437, 0xc7e3e427, 0x04202424, 0x84a0a424, 0xcbc3c80b, 0x43535013, 0x0a02080a, 0x87838407,
|
|
||||||
0xc9d1d819, 0x4c404c0c, 0x83838003, 0x8f838c0f, 0xcec2cc0e, 0x0b33383b, 0x4a42480a, 0x87b3b437
|
|
||||||
};
|
|
||||||
|
|
||||||
private static uint GetUIntFromByteArray(byte[] src, int srcOffset, ENDIAN endian = ENDIAN.BIG)
|
|
||||||
{
|
|
||||||
if (src == null || src.Length < srcOffset + 4)
|
|
||||||
throw new ArgumentException("Invalid source array or offset.");
|
|
||||||
|
|
||||||
return (uint)(endian == ENDIAN.BIG
|
|
||||||
? (src[srcOffset] & 0xFF) << 24 |
|
|
||||||
(src[srcOffset + 1] & 0xFF) << 16 |
|
|
||||||
(src[srcOffset + 2] & 0xFF) << 8 |
|
|
||||||
(src[srcOffset + 3] & 0xFF)
|
|
||||||
: (src[srcOffset] & 0xFF) |
|
|
||||||
(src[srcOffset + 1] & 0xFF) << 8 |
|
|
||||||
(src[srcOffset + 2] & 0xFF) << 16 |
|
|
||||||
(src[srcOffset + 3] & 0xFF) << 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte GetByteFromUInt(uint value, int position)
|
|
||||||
{
|
|
||||||
if (position < 0 || position >= 4)
|
|
||||||
throw new ArgumentException("Position must be between 0 and 3.");
|
|
||||||
|
|
||||||
return position > 0
|
|
||||||
? (byte)((value >> (8 * position)) & 0xFF)
|
|
||||||
: (byte)(value & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetByteToUIntArray(ref uint[] dst, int byteOffset, byte value, ENDIAN endian)
|
|
||||||
{
|
|
||||||
if (dst == null || byteOffset < 0 || byteOffset >= dst.Length * 4)
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(byteOffset), "Invalid byte offset.");
|
|
||||||
|
|
||||||
int uintIndex = byteOffset / 4;
|
|
||||||
int shiftValue = (endian == ENDIAN.BIG)
|
|
||||||
? (3 - byteOffset % 4) * 8
|
|
||||||
: (byteOffset % 4) * 8;
|
|
||||||
|
|
||||||
uint maskValue = (uint)(0xFF << shiftValue);
|
|
||||||
uint maskValue2 = ~maskValue;
|
|
||||||
uint valueToSet = (uint)(value & 0xFF) << shiftValue;
|
|
||||||
|
|
||||||
dst[uintIndex] = (dst[uintIndex] & maskValue2) | (valueToSet & maskValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte GetByteFromUIntArray(uint[] src, int byteOffset, ENDIAN endian)
|
|
||||||
{
|
|
||||||
if (src == null || byteOffset < 0 || byteOffset >= src.Length * 4)
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(byteOffset), "Invalid byte offset.");
|
|
||||||
|
|
||||||
int uintIndex = byteOffset / 4;
|
|
||||||
int shiftValue = (endian == ENDIAN.BIG)
|
|
||||||
? (3 - byteOffset % 4) * 8
|
|
||||||
: (byteOffset % 4) * 8;
|
|
||||||
|
|
||||||
return (byte)((src[uintIndex] >> shiftValue) & 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint[] ConvertToUIntArray(byte[] src, int inLen, ENDIAN endian = ENDIAN.BIG)
|
|
||||||
{
|
|
||||||
if (src == null)
|
|
||||||
throw new ArgumentNullException(nameof(src), "source cannot be null.");
|
|
||||||
|
|
||||||
if (inLen <= 0 || inLen > src.Length)
|
|
||||||
throw new ArgumentException("Invalid input length.", nameof(inLen));
|
|
||||||
|
|
||||||
int outLen = (inLen + 3) / 4;
|
|
||||||
uint[] data = new uint[outLen];
|
|
||||||
|
|
||||||
for (int i = 0; i < outLen; i++)
|
|
||||||
{
|
|
||||||
data[i] = GetUIntFromByteArray(src, i * 4, endian);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static byte[] ConvertToByteArray(uint[] src, int inLen, ENDIAN endian = ENDIAN.BIG)
|
|
||||||
{
|
|
||||||
if (src == null)
|
|
||||||
throw new ArgumentNullException(nameof(src), "source cannot be null.");
|
|
||||||
|
|
||||||
if (inLen <= 0 || inLen > src.Length)
|
|
||||||
throw new ArgumentException("Invalid input length.", nameof(inLen));
|
|
||||||
|
|
||||||
int outLen = inLen;
|
|
||||||
byte[] data = new byte[outLen];
|
|
||||||
|
|
||||||
for (int i = 0; i < outLen; i++)
|
|
||||||
{
|
|
||||||
data[i] = GetByteFromUIntArray(src, i, endian);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint Substitute(uint value)
|
|
||||||
{
|
|
||||||
return SS0[GetByteFromUInt(value, 0)] ^
|
|
||||||
SS1[GetByteFromUInt(value, 1)] ^
|
|
||||||
SS2[GetByteFromUInt(value, 2)] ^
|
|
||||||
SS3[GetByteFromUInt(value, 3)];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Round function F and adding output of F to L.
|
|
||||||
// L0, L1 : left input values at each round
|
|
||||||
// R0, R1 : right input values at each round
|
|
||||||
// K : round keys at each round
|
|
||||||
private static void SeedRound(ref uint[] T, ref uint[] LR, int L0, int L1, int R0, int R1, uint[] K, int K_offset)
|
|
||||||
{
|
|
||||||
T[0] = LR[R0] ^ K[K_offset + 0];
|
|
||||||
T[1] = LR[R1] ^ K[K_offset + 1];
|
|
||||||
T[1] ^= T[0];
|
|
||||||
T[1] = Substitute(T[1]);
|
|
||||||
T[0] += T[1];
|
|
||||||
T[0] = Substitute(T[0]);
|
|
||||||
T[1] += T[0];
|
|
||||||
T[1] = Substitute(T[1]);
|
|
||||||
T[0] += T[1];
|
|
||||||
LR[L0] ^= T[0]; LR[L1] ^= T[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint EndianChange(uint value)
|
|
||||||
{
|
|
||||||
return ((value & 0x000000FF) << 24) | // Move the first byte to the fourth byte position
|
|
||||||
((value & 0x0000FF00) << 8) | // Move the second byte to the third byte position
|
|
||||||
((value & 0x00FF0000) >> 8) | // Move the third byte to the second byte position
|
|
||||||
((value & 0xFF000000) >> 24); // Move the fourth byte to the first byte position
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void RoundKeyUpdate0(ref uint[] T, ref uint[] K, int K_offset, ref uint[] ABCD, uint KC)
|
|
||||||
{
|
|
||||||
T[0] = ABCD[ABCD_A] + ABCD[ABCD_C] - KC;
|
|
||||||
T[1] = ABCD[ABCD_B] + KC - ABCD[ABCD_D];
|
|
||||||
K[K_offset + 0] = Substitute(T[0]);
|
|
||||||
K[K_offset + 1] = Substitute(T[1]);
|
|
||||||
T[0] = ABCD[ABCD_A];
|
|
||||||
ABCD[ABCD_A] = ((ABCD[ABCD_A] >> 8) & 0x00ffffff) ^ (ABCD[ABCD_B] << 24);
|
|
||||||
ABCD[ABCD_B] = ((ABCD[ABCD_B] >> 8) & 0x00ffffff) ^ (T[0] << 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void RoundKeyUpdate1(ref uint[] T, ref uint[] K, int K_offset, ref uint[] ABCD, uint KC)
|
|
||||||
{
|
|
||||||
T[0] = ABCD[ABCD_A] + ABCD[ABCD_C] - KC;
|
|
||||||
T[1] = ABCD[ABCD_B] + KC - ABCD[ABCD_D];
|
|
||||||
K[K_offset + 0] = Substitute(T[0]);
|
|
||||||
K[K_offset + 1] = Substitute(T[1]);
|
|
||||||
T[0] = ABCD[ABCD_C];
|
|
||||||
ABCD[ABCD_C] = (ABCD[ABCD_C] << 8) ^ ((ABCD[ABCD_D] >> 24) & 0x000000ff);
|
|
||||||
ABCD[ABCD_D] = (ABCD[ABCD_D] << 8) ^ ((T[0] >> 24) & 0x000000ff);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ECB
|
|
||||||
{
|
|
||||||
public void EncryptBlock(in uint[] _in, int in_offset, ref uint[] _out, int out_offset, KISA_SEED_KEY ks)
|
|
||||||
{
|
|
||||||
uint[] LR = new uint[4]; // Iuput/output values at each rounds
|
|
||||||
uint[] T = new uint[2]; // Temporary variables for round function F
|
|
||||||
uint[] K = ks.key_data; // Pointer of round keys
|
|
||||||
|
|
||||||
// Set up input values for first round
|
|
||||||
LR[LR_L0] = _in[in_offset + 0];
|
|
||||||
LR[LR_L1] = _in[in_offset + 1];
|
|
||||||
LR[LR_R0] = _in[in_offset + 2];
|
|
||||||
LR[LR_R1] = _in[in_offset + 3];
|
|
||||||
|
|
||||||
// Reorder for big endian
|
|
||||||
// Because SEED use little endian order in default
|
|
||||||
if (ENDIAN.BIG != DEFAULT_ENDIAN)
|
|
||||||
{
|
|
||||||
LR[LR_L0] = EndianChange(LR[LR_L0]);
|
|
||||||
LR[LR_L1] = EndianChange(LR[LR_L1]);
|
|
||||||
LR[LR_R0] = EndianChange(LR[LR_R0]);
|
|
||||||
LR[LR_R1] = EndianChange(LR[LR_R1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
SeedRound(ref T, ref LR, LR_L0, LR_L1, LR_R0, LR_R1, K, 0); // Round 1
|
|
||||||
SeedRound(ref T, ref LR, LR_R0, LR_R1, LR_L0, LR_L1, K, 2); // Round 2
|
|
||||||
SeedRound(ref T, ref LR, LR_L0, LR_L1, LR_R0, LR_R1, K, 4); // Round 3
|
|
||||||
SeedRound(ref T, ref LR, LR_R0, LR_R1, LR_L0, LR_L1, K, 6); // Round 4
|
|
||||||
SeedRound(ref T, ref LR, LR_L0, LR_L1, LR_R0, LR_R1, K, 8); // Round 5
|
|
||||||
SeedRound(ref T, ref LR, LR_R0, LR_R1, LR_L0, LR_L1, K, 10); // Round 6
|
|
||||||
SeedRound(ref T, ref LR, LR_L0, LR_L1, LR_R0, LR_R1, K, 12); // Round 7
|
|
||||||
SeedRound(ref T, ref LR, LR_R0, LR_R1, LR_L0, LR_L1, K, 14); // Round 8
|
|
||||||
SeedRound(ref T, ref LR, LR_L0, LR_L1, LR_R0, LR_R1, K, 16); // Round 9
|
|
||||||
SeedRound(ref T, ref LR, LR_R0, LR_R1, LR_L0, LR_L1, K, 18); // Round 10
|
|
||||||
SeedRound(ref T, ref LR, LR_L0, LR_L1, LR_R0, LR_R1, K, 20); // Round 11
|
|
||||||
SeedRound(ref T, ref LR, LR_R0, LR_R1, LR_L0, LR_L1, K, 22); // Round 12
|
|
||||||
SeedRound(ref T, ref LR, LR_L0, LR_L1, LR_R0, LR_R1, K, 24); // Round 13
|
|
||||||
SeedRound(ref T, ref LR, LR_R0, LR_R1, LR_L0, LR_L1, K, 26); // Round 14
|
|
||||||
SeedRound(ref T, ref LR, LR_L0, LR_L1, LR_R0, LR_R1, K, 28); // Round 15
|
|
||||||
SeedRound(ref T, ref LR, LR_R0, LR_R1, LR_L0, LR_L1, K, 30); // Round 16
|
|
||||||
|
|
||||||
if (ENDIAN.BIG != DEFAULT_ENDIAN)
|
|
||||||
{
|
|
||||||
LR[LR_L0] = EndianChange(LR[LR_L0]);
|
|
||||||
LR[LR_L1] = EndianChange(LR[LR_L1]);
|
|
||||||
LR[LR_R0] = EndianChange(LR[LR_R0]);
|
|
||||||
LR[LR_R1] = EndianChange(LR[LR_R1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copying output values from last round to pbData
|
|
||||||
_out[out_offset + 0] = LR[LR_R0];
|
|
||||||
_out[out_offset + 1] = LR[LR_R1];
|
|
||||||
_out[out_offset + 2] = LR[LR_L0];
|
|
||||||
_out[out_offset + 3] = LR[LR_L1];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void DecryptBlock(in uint[] _in, int in_offset, ref uint[] _out, int out_offset, KISA_SEED_KEY ks)
|
|
||||||
{
|
|
||||||
uint[] LR = new uint[4]; // Iuput/output values at each rounds
|
|
||||||
uint[] T = new uint[2]; // Temporary variables for round function F
|
|
||||||
uint[] K = ks.key_data; // Pointer of round keys
|
|
||||||
|
|
||||||
// Set up input values for first round
|
|
||||||
LR[LR_L0] = _in[in_offset + 0];
|
|
||||||
LR[LR_L1] = _in[in_offset + 1];
|
|
||||||
LR[LR_R0] = _in[in_offset + 2];
|
|
||||||
LR[LR_R1] = _in[in_offset + 3];
|
|
||||||
|
|
||||||
// Reorder for big endian
|
|
||||||
if (ENDIAN.BIG != DEFAULT_ENDIAN)
|
|
||||||
{
|
|
||||||
LR[LR_L0] = EndianChange(LR[LR_L0]);
|
|
||||||
LR[LR_L1] = EndianChange(LR[LR_L1]);
|
|
||||||
LR[LR_R0] = EndianChange(LR[LR_R0]);
|
|
||||||
LR[LR_R1] = EndianChange(LR[LR_R1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
SeedRound(ref T, ref LR, LR_L0, LR_L1, LR_R0, LR_R1, K, 30); // Round 1
|
|
||||||
SeedRound(ref T, ref LR, LR_R0, LR_R1, LR_L0, LR_L1, K, 28); // Round 2
|
|
||||||
SeedRound(ref T, ref LR, LR_L0, LR_L1, LR_R0, LR_R1, K, 26); // Round 3
|
|
||||||
SeedRound(ref T, ref LR, LR_R0, LR_R1, LR_L0, LR_L1, K, 24); // Round 4
|
|
||||||
SeedRound(ref T, ref LR, LR_L0, LR_L1, LR_R0, LR_R1, K, 22); // Round 5
|
|
||||||
SeedRound(ref T, ref LR, LR_R0, LR_R1, LR_L0, LR_L1, K, 20); // Round 6
|
|
||||||
SeedRound(ref T, ref LR, LR_L0, LR_L1, LR_R0, LR_R1, K, 18); // Round 7
|
|
||||||
SeedRound(ref T, ref LR, LR_R0, LR_R1, LR_L0, LR_L1, K, 16); // Round 8
|
|
||||||
SeedRound(ref T, ref LR, LR_L0, LR_L1, LR_R0, LR_R1, K, 14); // Round 9
|
|
||||||
SeedRound(ref T, ref LR, LR_R0, LR_R1, LR_L0, LR_L1, K, 12); // Round 10
|
|
||||||
SeedRound(ref T, ref LR, LR_L0, LR_L1, LR_R0, LR_R1, K, 10); // Round 11
|
|
||||||
SeedRound(ref T, ref LR, LR_R0, LR_R1, LR_L0, LR_L1, K, 8); // Round 12
|
|
||||||
SeedRound(ref T, ref LR, LR_L0, LR_L1, LR_R0, LR_R1, K, 6); // Round 13
|
|
||||||
SeedRound(ref T, ref LR, LR_R0, LR_R1, LR_L0, LR_L1, K, 4); // Round 14
|
|
||||||
SeedRound(ref T, ref LR, LR_L0, LR_L1, LR_R0, LR_R1, K, 2); // Round 15
|
|
||||||
SeedRound(ref T, ref LR, LR_R0, LR_R1, LR_L0, LR_L1, K, 0); // Round 16
|
|
||||||
|
|
||||||
if (ENDIAN.BIG != DEFAULT_ENDIAN)
|
|
||||||
{
|
|
||||||
LR[LR_L0] = EndianChange(LR[LR_L0]);
|
|
||||||
LR[LR_L1] = EndianChange(LR[LR_L1]);
|
|
||||||
LR[LR_R0] = EndianChange(LR[LR_R0]);
|
|
||||||
LR[LR_R1] = EndianChange(LR[LR_R1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy output values from last round to pbData
|
|
||||||
_out[out_offset + 0] = LR[LR_R0];
|
|
||||||
_out[out_offset + 1] = LR[LR_R1];
|
|
||||||
_out[out_offset + 2] = LR[LR_L0];
|
|
||||||
_out[out_offset + 3] = LR[LR_L1];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Init(KISA_SEED_INFO pInfo, KISA_ENC_DEC enc, byte[] pbszUserKey)
|
|
||||||
{
|
|
||||||
uint[] ABCD = new uint[4]; // Iuput/output values at each rounds
|
|
||||||
uint[] T = new uint[2]; // Temporary variable
|
|
||||||
uint[] K;
|
|
||||||
|
|
||||||
if (pInfo == null || pbszUserKey == null)
|
|
||||||
throw new ArgumentException("Invalid arguments");
|
|
||||||
|
|
||||||
K = pInfo.seed_key.key_data; // Pointer of round keys
|
|
||||||
|
|
||||||
pInfo.encrypt = enc.value;
|
|
||||||
pInfo.last_block_flag = pInfo.buffer_length = 0;
|
|
||||||
|
|
||||||
// Set up input values for Key Schedule
|
|
||||||
ABCD[ABCD_A] = GetUIntFromByteArray(pbszUserKey, 0 * 4, DEFAULT_ENDIAN);
|
|
||||||
ABCD[ABCD_B] = GetUIntFromByteArray(pbszUserKey, 1 * 4, DEFAULT_ENDIAN);
|
|
||||||
ABCD[ABCD_C] = GetUIntFromByteArray(pbszUserKey, 2 * 4, DEFAULT_ENDIAN);
|
|
||||||
ABCD[ABCD_D] = GetUIntFromByteArray(pbszUserKey, 3 * 4, DEFAULT_ENDIAN);
|
|
||||||
|
|
||||||
// Reorder for big endian
|
|
||||||
if (ENDIAN.BIG != DEFAULT_ENDIAN)
|
|
||||||
{
|
|
||||||
ABCD[ABCD_A] = EndianChange(ABCD[ABCD_A]);
|
|
||||||
ABCD[ABCD_B] = EndianChange(ABCD[ABCD_B]);
|
|
||||||
ABCD[ABCD_C] = EndianChange(ABCD[ABCD_C]);
|
|
||||||
ABCD[ABCD_D] = EndianChange(ABCD[ABCD_D]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// i-th round keys( K_i,0 and K_i,1 ) are denoted as K[2*(i-1)] and K[2*i-1], respectively
|
|
||||||
RoundKeyUpdate0(ref T, ref K, 0, ref ABCD, KC0); // K_1,0 and K_1,1
|
|
||||||
RoundKeyUpdate1(ref T, ref K, 2, ref ABCD, KC1); // K_2,0 and K_2,1
|
|
||||||
RoundKeyUpdate0(ref T, ref K, 4, ref ABCD, KC2); // K_3,0 and K_3,1
|
|
||||||
RoundKeyUpdate1(ref T, ref K, 6, ref ABCD, KC3); // K_4,0 and K_4,1
|
|
||||||
RoundKeyUpdate0(ref T, ref K, 8, ref ABCD, KC4); // K_5,0 and K_5,1
|
|
||||||
RoundKeyUpdate1(ref T, ref K, 10, ref ABCD, KC5); // K_6,0 and K_6,1
|
|
||||||
RoundKeyUpdate0(ref T, ref K, 12, ref ABCD, KC6); // K_7,0 and K_7,1
|
|
||||||
RoundKeyUpdate1(ref T, ref K, 14, ref ABCD, KC7); // K_8,0 and K_8,1
|
|
||||||
RoundKeyUpdate0(ref T, ref K, 16, ref ABCD, KC8); // K_9,0 and K_9,1
|
|
||||||
RoundKeyUpdate1(ref T, ref K, 18, ref ABCD, KC9); // K_10,0 and K_10,1
|
|
||||||
RoundKeyUpdate0(ref T, ref K, 20, ref ABCD, KC10); // K_11,0 and K_11,1
|
|
||||||
RoundKeyUpdate1(ref T, ref K, 22, ref ABCD, KC11); // K_12,0 and K_12,1
|
|
||||||
RoundKeyUpdate0(ref T, ref K, 24, ref ABCD, KC12); // K_13,0 and K_13,1
|
|
||||||
RoundKeyUpdate1(ref T, ref K, 26, ref ABCD, KC13); // K_14,0 and K_14,1
|
|
||||||
RoundKeyUpdate0(ref T, ref K, 28, ref ABCD, KC14); // K_15,0 and K_15,1
|
|
||||||
|
|
||||||
T[0] = ABCD[ABCD_A] + ABCD[ABCD_C] - KC15;
|
|
||||||
T[1] = ABCD[ABCD_B] - ABCD[ABCD_D] + KC15;
|
|
||||||
|
|
||||||
K[30] = SS0[GetByteFromUInt(T[0], 0) & 0x0ff] ^ SS1[GetByteFromUInt(T[0], 1) & 0x0ff] ^ // K_16,0
|
|
||||||
SS2[GetByteFromUInt(T[0], 2) & 0x0ff] ^ SS3[GetByteFromUInt(T[0], 3) & 0x0ff];
|
|
||||||
K[31] = SS0[GetByteFromUInt(T[1], 0) & 0x0ff] ^ SS1[GetByteFromUInt(T[1], 1) & 0x0ff] ^ // K_16,1
|
|
||||||
SS2[GetByteFromUInt(T[1], 2) & 0x0ff] ^ SS3[GetByteFromUInt(T[1], 3) & 0x0ff];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Process(KISA_SEED_INFO pInfo, in uint[] _in, int inLen, ref uint[] _out, ref int[] outLen)
|
|
||||||
{
|
|
||||||
int nCurrentCount = BLOCK_SIZE_SEED;
|
|
||||||
int in_offset = 0;
|
|
||||||
int out_offset = 0;
|
|
||||||
|
|
||||||
if (pInfo == null || _in == null || _out == null || inLen <= 0)
|
|
||||||
throw new ArgumentException("Invalid arguments.");
|
|
||||||
|
|
||||||
if (KISA_ENC_DEC._KISA_ENCRYPT == pInfo.encrypt)
|
|
||||||
{
|
|
||||||
while (nCurrentCount <= inLen)
|
|
||||||
{
|
|
||||||
EncryptBlock(_in, in_offset, ref _out, out_offset, pInfo.seed_key);
|
|
||||||
nCurrentCount += BLOCK_SIZE_SEED;
|
|
||||||
in_offset += BLOCK_SIZE_SEED_INT;
|
|
||||||
out_offset += BLOCK_SIZE_SEED_INT;
|
|
||||||
}
|
|
||||||
|
|
||||||
outLen[0] = nCurrentCount - BLOCK_SIZE_SEED;
|
|
||||||
pInfo.buffer_length = inLen - outLen[0];
|
|
||||||
Array.Copy(_in, in_offset, pInfo.ecb_buffer, 0, pInfo.buffer_length);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while (nCurrentCount <= inLen)
|
|
||||||
{
|
|
||||||
DecryptBlock(_in, in_offset, ref _out, out_offset, pInfo.seed_key);
|
|
||||||
nCurrentCount += BLOCK_SIZE_SEED;
|
|
||||||
in_offset += BLOCK_SIZE_SEED_INT;
|
|
||||||
out_offset += BLOCK_SIZE_SEED_INT;
|
|
||||||
}
|
|
||||||
outLen[0] = nCurrentCount - BLOCK_SIZE_SEED;
|
|
||||||
Array.Copy(_out, out_offset - BLOCK_SIZE_SEED_INT, pInfo.ecb_last_block, 0, BLOCK_SIZE_SEED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Close(KISA_SEED_INFO pInfo, uint[] _out, int out_offset, ref int[] outLen)
|
|
||||||
{
|
|
||||||
int nPaddngLen;
|
|
||||||
|
|
||||||
outLen[0] = 0;
|
|
||||||
|
|
||||||
if (_out == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (KISA_ENC_DEC._KISA_ENCRYPT == pInfo.encrypt)
|
|
||||||
{
|
|
||||||
nPaddngLen = BLOCK_SIZE_SEED - pInfo.buffer_length;
|
|
||||||
for (int i = pInfo.buffer_length; i < BLOCK_SIZE_SEED; i++)
|
|
||||||
{
|
|
||||||
SetByteToUIntArray(ref pInfo.ecb_buffer, i, (byte)nPaddngLen, DEFAULT_ENDIAN);
|
|
||||||
}
|
|
||||||
EncryptBlock(pInfo.ecb_buffer, 0, ref _out, (out_offset) / 4, pInfo.seed_key);
|
|
||||||
outLen[0] = BLOCK_SIZE_SEED;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nPaddngLen = GetByteFromUIntArray(pInfo.ecb_last_block, BLOCK_SIZE_SEED - 1, DEFAULT_ENDIAN);
|
|
||||||
if (nPaddngLen > 0 && nPaddngLen <= BLOCK_SIZE_SEED)
|
|
||||||
{
|
|
||||||
for (int i = nPaddngLen; i > 0; i--)
|
|
||||||
{
|
|
||||||
SetByteToUIntArray(ref _out, out_offset - i, (byte)0x00, DEFAULT_ENDIAN);
|
|
||||||
}
|
|
||||||
outLen[0] = nPaddngLen;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] Encrypt(byte[] pbszUserKey, byte[] pbData, int offset, int length)
|
|
||||||
{
|
|
||||||
KISA_SEED_INFO info = new KISA_SEED_INFO();
|
|
||||||
uint[] _out;
|
|
||||||
uint[] data;
|
|
||||||
byte[] cdata;
|
|
||||||
int outLen;
|
|
||||||
int[] nRetOutLen = new int[] { 0 };
|
|
||||||
int[] nPaddingLen = new int[] { 0 };
|
|
||||||
|
|
||||||
byte[] pbszPlainText = new byte[length];
|
|
||||||
Array.Copy(pbData, offset, pbszPlainText, 0, length);
|
|
||||||
int nPlainTextLen = length;
|
|
||||||
|
|
||||||
int nPlainTextPadding = (BLOCK_SIZE_SEED - (nPlainTextLen) % BLOCK_SIZE_SEED);
|
|
||||||
byte[] newpbszPlainText = new byte[nPlainTextLen + nPlainTextPadding];
|
|
||||||
Array.Copy(pbszPlainText, newpbszPlainText, nPlainTextLen);
|
|
||||||
|
|
||||||
byte[] pbszCipherText = new byte[nPlainTextLen + nPlainTextPadding];
|
|
||||||
|
|
||||||
Init(info, KISA_ENC_DEC.KISA_ENCRYPT, pbszUserKey);
|
|
||||||
|
|
||||||
outLen = ((nPlainTextLen / 16) + 1) * 4;
|
|
||||||
|
|
||||||
_out = new uint[outLen];
|
|
||||||
|
|
||||||
data = ConvertToUIntArray(newpbszPlainText, nPlainTextLen);
|
|
||||||
Process(info, data, nPlainTextLen, ref _out, ref nRetOutLen);
|
|
||||||
Close(info, _out, nRetOutLen[0], ref nPaddingLen);
|
|
||||||
|
|
||||||
cdata = ConvertToByteArray(_out, nRetOutLen[0] + nPaddingLen[0]);
|
|
||||||
Array.Copy(cdata, pbszCipherText, nRetOutLen[0] + nPaddingLen[0]);
|
|
||||||
|
|
||||||
data = null;
|
|
||||||
cdata = null;
|
|
||||||
_out = null;
|
|
||||||
|
|
||||||
return pbszCipherText;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] Decrypt(byte[] pbszUserKey, byte[] pbData, int offset, int length)
|
|
||||||
{
|
|
||||||
byte[] result = new byte[] { };
|
|
||||||
|
|
||||||
KISA_SEED_INFO info = new KISA_SEED_INFO();
|
|
||||||
uint[] _out;
|
|
||||||
uint[] data;
|
|
||||||
byte[] cdata;
|
|
||||||
int outLen = 0;
|
|
||||||
int[] nRetOutLen = new int[] { 0 };
|
|
||||||
int[] nPaddingLen = new int[] { 0 };
|
|
||||||
|
|
||||||
byte[] pbszCipherText = pbData;
|
|
||||||
int nCipherTextLen = length;
|
|
||||||
|
|
||||||
if (nCipherTextLen % BLOCK_SIZE_SEED > 0)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] newpbszCipherText = new byte[nCipherTextLen];
|
|
||||||
Array.Copy(pbszCipherText, newpbszCipherText, nCipherTextLen);
|
|
||||||
|
|
||||||
byte[] pbszPlainText = new byte[nCipherTextLen];
|
|
||||||
|
|
||||||
Init(info, KISA_ENC_DEC.KISA_DECRYPT, pbszUserKey);
|
|
||||||
|
|
||||||
outLen = (nCipherTextLen / 16) * 4;
|
|
||||||
_out = new uint[outLen];
|
|
||||||
data = ConvertToUIntArray(newpbszCipherText, nCipherTextLen);
|
|
||||||
Process(info, data, nCipherTextLen, ref _out, ref nRetOutLen);
|
|
||||||
if (Close(info, _out, nRetOutLen[0], ref nPaddingLen))
|
|
||||||
{
|
|
||||||
cdata = ConvertToByteArray(_out, nRetOutLen[0] - nPaddingLen[0]);
|
|
||||||
Array.Copy(cdata, pbszPlainText, nRetOutLen[0] - nPaddingLen[0]);
|
|
||||||
int message_length = nRetOutLen[0] - nPaddingLen[0];
|
|
||||||
|
|
||||||
if (message_length < 0)
|
|
||||||
{
|
|
||||||
message_length = 0;
|
|
||||||
}
|
|
||||||
result = new byte[message_length];
|
|
||||||
Array.Copy(pbszPlainText, 0, result, 0, message_length);
|
|
||||||
|
|
||||||
data = null;
|
|
||||||
cdata = null;
|
|
||||||
_out = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetDefaultEndian(ENDIAN endian)
|
|
||||||
{
|
|
||||||
DEFAULT_ENDIAN = endian;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class KISA_ENC_DEC
|
|
||||||
{
|
|
||||||
public const int _KISA_DECRYPT = 0;
|
|
||||||
public const int _KISA_ENCRYPT = 1;
|
|
||||||
|
|
||||||
public int value;
|
|
||||||
|
|
||||||
public KISA_ENC_DEC(int value)
|
|
||||||
{
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static KISA_ENC_DEC KISA_ENCRYPT = new KISA_ENC_DEC(_KISA_ENCRYPT);
|
|
||||||
public static KISA_ENC_DEC KISA_DECRYPT = new KISA_ENC_DEC(_KISA_DECRYPT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class KISA_SEED_KEY
|
|
||||||
{
|
|
||||||
public uint[] key_data = new uint[32];
|
|
||||||
|
|
||||||
public void Init()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < key_data.Length; i++)
|
|
||||||
{
|
|
||||||
key_data[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class KISA_SEED_INFO
|
|
||||||
{
|
|
||||||
public int encrypt;
|
|
||||||
public KISA_SEED_KEY seed_key = new KISA_SEED_KEY();
|
|
||||||
public uint[] ecb_buffer = new uint[4];
|
|
||||||
public int buffer_length;
|
|
||||||
public uint[] ecb_last_block = new uint[4];
|
|
||||||
public int last_block_flag;
|
|
||||||
|
|
||||||
public KISA_SEED_INFO()
|
|
||||||
{
|
|
||||||
encrypt = 0;
|
|
||||||
seed_key.Init();
|
|
||||||
ecb_buffer[0] = ecb_buffer[1] = ecb_buffer[2] = ecb_buffer[3] = 0;
|
|
||||||
buffer_length = 0;
|
|
||||||
ecb_last_block[0] = ecb_last_block[1] = ecb_last_block[2] = ecb_last_block[3] = 0;
|
|
||||||
last_block_flag = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,11 +6,11 @@ using System.Runtime.InteropServices;
|
||||||
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
|
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
|
||||||
// 이러한 특성 값을 변경하세요.
|
// 이러한 특성 값을 변경하세요.
|
||||||
[assembly: AssemblyTitle("WelsonJS.Toolkit")]
|
[assembly: AssemblyTitle("WelsonJS.Toolkit")]
|
||||||
[assembly: AssemblyDescription("Toolkit for WelsonJS framework based applications")]
|
[assembly: AssemblyDescription("Toolkit for WelsonJS framework")]
|
||||||
[assembly: AssemblyConfiguration("")]
|
[assembly: AssemblyConfiguration("")]
|
||||||
[assembly: AssemblyCompany("Catswords")]
|
[assembly: AssemblyCompany("Catswords")]
|
||||||
[assembly: AssemblyProduct("WelsonJS")]
|
[assembly: AssemblyProduct("WelsonJS")]
|
||||||
[assembly: AssemblyCopyright("Catswords OSS, GPLv3 or Ms-RL")]
|
[assembly: AssemblyCopyright("Catswords OSS, C-2021-000237, Opensource licensed under GPLv3 or MS-RL")]
|
||||||
[assembly: AssemblyTrademark("WelsonJS")]
|
[assembly: AssemblyTrademark("WelsonJS")]
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||||
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
|
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
|
||||||
// 기본값으로 할 수 있습니다.
|
// 기본값으로 할 수 있습니다.
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("0.2.7.54")]
|
[assembly: AssemblyVersion("0.2.7.22")]
|
||||||
[assembly: AssemblyFileVersion("0.2.7.54")]
|
[assembly: AssemblyFileVersion("0.2.7.22")]
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
|
|
|
@ -225,7 +225,7 @@ namespace WelsonJS
|
||||||
}
|
}
|
||||||
|
|
||||||
[ComVisible(true)]
|
[ComVisible(true)]
|
||||||
public string EncryptString(string key, string data)
|
public string EncryptStringHIGHT(string key, string data)
|
||||||
{
|
{
|
||||||
byte[] userKey = Encoding.ASCII.GetBytes(key);
|
byte[] userKey = Encoding.ASCII.GetBytes(key);
|
||||||
byte[] dataIn = Encoding.UTF8.GetBytes(data);
|
byte[] dataIn = Encoding.UTF8.GetBytes(data);
|
||||||
|
@ -235,7 +235,7 @@ namespace WelsonJS
|
||||||
}
|
}
|
||||||
|
|
||||||
[ComVisible(true)]
|
[ComVisible(true)]
|
||||||
public string DecryptString(string key, string encryptedData)
|
public string DecryptStringHIGHT(string key, string encryptedData)
|
||||||
{
|
{
|
||||||
byte[] userKey = Encoding.ASCII.GetBytes(key);
|
byte[] userKey = Encoding.ASCII.GetBytes(key);
|
||||||
byte[] dataIn = Convert.FromBase64String(encryptedData);
|
byte[] dataIn = Convert.FromBase64String(encryptedData);
|
||||||
|
|
|
@ -79,7 +79,6 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<ApplicationIcon>favicon.ico</ApplicationIcon>
|
<ApplicationIcon>favicon.ico</ApplicationIcon>
|
||||||
<PackageIcon>icon.png</PackageIcon>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
@ -89,12 +88,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="BitmapUtils.cs" />
|
<Compile Include="BitmapUtils.cs" />
|
||||||
<Compile Include="Compression\LZ77.cs" />
|
<Compile Include="Compression\LZ77.cs" />
|
||||||
<Compile Include="Cryptography\AnsiX923Padding.cs" />
|
|
||||||
<Compile Include="Cryptography\ARIA.cs" />
|
|
||||||
<Compile Include="Cryptography\HIGHT.cs" />
|
<Compile Include="Cryptography\HIGHT.cs" />
|
||||||
<Compile Include="Cryptography\LEA.cs" />
|
|
||||||
<Compile Include="Cryptography\PKCS5Padding.cs" />
|
|
||||||
<Compile Include="Cryptography\SEED.cs" />
|
|
||||||
<Compile Include="NamedSharedMemory.cs" />
|
<Compile Include="NamedSharedMemory.cs" />
|
||||||
<Compile Include="ProcessUtils.cs" />
|
<Compile Include="ProcessUtils.cs" />
|
||||||
<Compile Include="Prompt.cs" />
|
<Compile Include="Prompt.cs" />
|
||||||
|
@ -106,8 +100,6 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="welsonjs.snk" />
|
<None Include="welsonjs.snk" />
|
||||||
<None Include="WelsonJS.Toolkit.nuspec" />
|
|
||||||
<None Include="assets/img/logo.png" Pack="true" PackagePath="" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="favicon.ico" />
|
<Content Include="favicon.ico" />
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<package >
|
|
||||||
<metadata>
|
|
||||||
<id>$id$</id>
|
|
||||||
<version>0.2.7.49</version>
|
|
||||||
<title>$title$</title>
|
|
||||||
<authors>Namhyeon Go, Catswords OSS</authors>
|
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
|
||||||
<license type="expression">GPL-3.0-only</license>
|
|
||||||
<icon>logo.png</icon>
|
|
||||||
<readme>README.md</readme>
|
|
||||||
<projectUrl>https://github.com/gnh1201/welsonjs</projectUrl>
|
|
||||||
<description>Native toolkit for WelsonJS framework-based RPA applications.</description>
|
|
||||||
<releaseNotes>Updated release</releaseNotes>
|
|
||||||
<copyright>$copyright$</copyright>
|
|
||||||
<tags>rpa com scripting library javascript ini window-handle named-shared-memory</tags>
|
|
||||||
</metadata>
|
|
||||||
<files>
|
|
||||||
<file src="assets\img\logo.png" />
|
|
||||||
<file src="assets\docs\README.md" />
|
|
||||||
</files>
|
|
||||||
</package>
|
|
|
@ -1,17 +0,0 @@
|
||||||
# WelsonJS.Toolkit
|
|
||||||
|
|
||||||
WelsonJS.Toolkit is a native toolkit for WelsonJS. Of course, it can also be used in other projects.
|
|
||||||
|
|
||||||
This library supports COM and provides the following features:
|
|
||||||
|
|
||||||
* Access and control Windows handles
|
|
||||||
* Send keyboard and mouse click commands to Windows handles
|
|
||||||
* Use Named Shared Memory
|
|
||||||
* Read and modify INI files
|
|
||||||
* Encryption (HIGHT)
|
|
||||||
* Compression (LZ77)
|
|
||||||
* Bitmap handling
|
|
||||||
|
|
||||||
For more details, refer to the [WelsonJS Documentation](https://catswords-oss.rdbl.io/5719744820/5330609327).
|
|
||||||
|
|
||||||
Source code available: https://github.com/gnh1201/welsonjs
|
|
Before Width: | Height: | Size: 6.7 KiB |
132
app.js
|
@ -1,16 +1,48 @@
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
// app.js
|
// app.js
|
||||||
|
//
|
||||||
// Bootstrap code for running a javascript app in windows. Run as:
|
// Bootstrap code for running a javascript app in windows. Run as:
|
||||||
|
//
|
||||||
// cscript.js app.js <appname> <app arguments> ...
|
// cscript.js app.js <appname> <app arguments> ...
|
||||||
//
|
//
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
// Author: Namhyeon Go <abuse@catswords.net>
|
// Author: Namhyeon Go <abuse@catswords.net>
|
||||||
// Repository: https://github.com/gnh1201/welsonjs
|
// Repository: https://github.com/gnh1201/welsonjs
|
||||||
// License: GPLv3 or MS-RL (Opensource)
|
|
||||||
// Report abuse: abuse@catswords.net
|
// Report abuse: abuse@catswords.net
|
||||||
// Latest news: ActivityPub @catswords_oss@catswords.social
|
// Latest news: ActivityPub @catswords_oss@catswords.social
|
||||||
// Join our team: https://teams.live.com/l/community/FEACHncAhq8ldnojAI
|
// Join our team: https://teams.live.com/l/community/FEACHncAhq8ldnojAI
|
||||||
//
|
//
|
||||||
"use strict";
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Bootstrap code, basic module loading functionality
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//
|
||||||
|
// The module loaded is run inside a function, with one argument, global which
|
||||||
|
// points to the global context. So global.FN is the same as FN (as long as a
|
||||||
|
// version of FN does not exist in local scope).
|
||||||
|
//
|
||||||
|
// The module should return its interface at the end of the script. The basic
|
||||||
|
// pattern for a module is:-
|
||||||
|
//
|
||||||
|
// var module = { ... };
|
||||||
|
// return module;
|
||||||
|
//
|
||||||
|
// Or:-
|
||||||
|
//
|
||||||
|
// return function() {
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// The appname argument causes <appname>.js to be loaded. The interface returned
|
||||||
|
// must define main = function(args) {}, which is called once the module is
|
||||||
|
// loaded.
|
||||||
|
//
|
||||||
var exit = function(status) {
|
var exit = function(status) {
|
||||||
console.error("Exit", status, "caused");
|
console.error("Exit", status, "caused");
|
||||||
|
|
||||||
|
@ -46,7 +78,7 @@ var console = {
|
||||||
},
|
},
|
||||||
_echoCallback: null,
|
_echoCallback: null,
|
||||||
_echo: function(args, type) {
|
_echo: function(args, type) {
|
||||||
var messages = [];
|
var message = "";
|
||||||
var params = {
|
var params = {
|
||||||
type: type,
|
type: type,
|
||||||
scope: [],
|
scope: [],
|
||||||
|
@ -54,41 +86,32 @@ var console = {
|
||||||
datetime: new Date().toISOString()
|
datetime: new Date().toISOString()
|
||||||
};
|
};
|
||||||
|
|
||||||
var argl = args.length;
|
if (args.length > 0) {
|
||||||
for (var i = 0; i < argl; i++) {
|
if (typeof args[0] === "string") {
|
||||||
switch (typeof args[i]) {
|
// if not type is "log", then "{type}: {message}"
|
||||||
case "string":
|
|
||||||
messages.push(args[i]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "number":
|
|
||||||
case "boolean":
|
|
||||||
messages.push(String(args[i]));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "object":
|
|
||||||
if ("message" in args[i]) {
|
|
||||||
messages.push(args[i].message);
|
|
||||||
for (var k in args[i]) {
|
|
||||||
params[k] = args[i][k];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
messages.push("[object Object]");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "unknown":
|
|
||||||
messages.push("[unknown]");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var message = messages.join(' ');
|
|
||||||
if (typeof type !== "undefined") {
|
if (typeof type !== "undefined") {
|
||||||
message = type + ": " + message;
|
message += (type + ": " + this._join(args));
|
||||||
|
} else {
|
||||||
|
message += this._join(args);
|
||||||
}
|
}
|
||||||
this._echoDefault(message);
|
this._echoDefault(message);
|
||||||
this._messages.push(message);
|
this._messages.push(message);
|
||||||
|
params.message = message;
|
||||||
|
} else if (typeof args[0] === "object") {
|
||||||
|
if ('message' in args[0]) {
|
||||||
|
if (typeof type !== "undefined") {
|
||||||
|
message += (type + ": " + args[0].message);
|
||||||
|
} else {
|
||||||
|
message += args[0].message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._echoDefault(message);
|
||||||
|
this._messages.push(args[0].message);
|
||||||
|
for (var k in args[0]) {
|
||||||
|
params[k] = args[0][k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (params.scope.length > 0 && this._echoCallback != null) {
|
if (params.scope.length > 0 && this._echoCallback != null) {
|
||||||
try {
|
try {
|
||||||
|
@ -215,12 +238,10 @@ function require(pathname) {
|
||||||
if (cache[FN]) return cache[FN];
|
if (cache[FN]) return cache[FN];
|
||||||
|
|
||||||
var T = null;
|
var T = null;
|
||||||
var sep = '://', pos = FN.indexOf(sep);
|
var pos = FN.indexOf('://');
|
||||||
if (pos > -1) {
|
|
||||||
var scheme = FN.substring(0, pos);
|
|
||||||
|
|
||||||
// load script from a remote server
|
if (pos > -1) { // from a remote server
|
||||||
if (["http", "https"].indexOf(scheme) > -1) {
|
if (["http", "https"].indexOf(FN.substring(0, pos)) > -1) {
|
||||||
require._addScriptProvider(function(url) {
|
require._addScriptProvider(function(url) {
|
||||||
try {
|
try {
|
||||||
return require("lib/http").get(url);
|
return require("lib/http").get(url);
|
||||||
|
@ -230,24 +251,6 @@ function require(pathname) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// load script from LIE(Language Inference Engine) service
|
|
||||||
if (["ai"].indexOf(scheme) > -1) {
|
|
||||||
require._addScriptProvider(function(url) {
|
|
||||||
try {
|
|
||||||
var text = url.substring(pos + sep.length);
|
|
||||||
return require("lib/language-inference-engine")
|
|
||||||
.create()
|
|
||||||
.setProvider("openai")
|
|
||||||
.inference(text, 0)
|
|
||||||
.join(' ')
|
|
||||||
;
|
|
||||||
} catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// if exists the custom script providers
|
|
||||||
if (require._scriptProviders.length > 0) {
|
if (require._scriptProviders.length > 0) {
|
||||||
var i = 0;
|
var i = 0;
|
||||||
while (T == null && i < require._scriptProviders.length) {
|
while (T == null && i < require._scriptProviders.length) {
|
||||||
|
@ -260,8 +263,7 @@ function require(pathname) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else { // from a local server
|
||||||
// load script from a local server
|
|
||||||
var _filename = (function(fs, path) {
|
var _filename = (function(fs, path) {
|
||||||
var filepaths = [
|
var filepaths = [
|
||||||
FN, // default
|
FN, // default
|
||||||
|
@ -345,7 +347,7 @@ function require(pathname) {
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ".enc": // encrypted script (require WelsonJS.Toolkit)
|
case ".enc": // protected script (HIGHT, ISO/IEC 18033-3)
|
||||||
T = (function(data, o) {
|
T = (function(data, o) {
|
||||||
try {
|
try {
|
||||||
var s = '', i = 0, k = 6;
|
var s = '', i = 0, k = 6;
|
||||||
|
@ -357,7 +359,7 @@ function require(pathname) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (i == k) return '';
|
if (i == k) return '';
|
||||||
return o.DecryptString(s, data);
|
return o.DecryptStringHIGHT(s, data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Failed to load the encrypted data:", e.message);
|
console.error("Failed to load the encrypted data:", e.message);
|
||||||
return '';
|
return '';
|
||||||
|
@ -663,7 +665,7 @@ if (typeof JSON === "undefined") {
|
||||||
require("app/assets/js/core-js-3.38.0.minified");
|
require("app/assets/js/core-js-3.38.0.minified");
|
||||||
|
|
||||||
// Squel.js SQL query string builder for Javascript
|
// Squel.js SQL query string builder for Javascript
|
||||||
var squel = require("app/assets/js/squel-basic-5.13.0-afa1cb5.wsh");
|
var squel = require("app/assets/js/squel-basic-5.13.0.hiddentao-afa1cb5.wsh");
|
||||||
|
|
||||||
// JavaScript YAML parser and dumper.
|
// JavaScript YAML parser and dumper.
|
||||||
var yaml = require("app/assets/js/js-yaml-4.1.0.wsh");
|
var yaml = require("app/assets/js/js-yaml-4.1.0.wsh");
|
||||||
|
@ -675,9 +677,6 @@ var is = require("app/assets/js/is-0.9.0.min");
|
||||||
//var Intl = require("app/assets/js/Intl-1.2.5-e93b114.min");
|
//var Intl = require("app/assets/js/Intl-1.2.5-e93b114.min");
|
||||||
//console.log(new Intl.NumberFormat().format(1234567890.123456));
|
//console.log(new Intl.NumberFormat().format(1234567890.123456));
|
||||||
|
|
||||||
// numbers.js - Advanced Mathematics Library for Node.js and JavaScript
|
|
||||||
var numbers = require("app/assets/js/numbers-0.7.0.wsh");
|
|
||||||
|
|
||||||
// linq.js - LINQ for JavaScript
|
// linq.js - LINQ for JavaScript
|
||||||
var Enumerable = require("app/assets/js/linq-4.0.2.wsh")._default;
|
var Enumerable = require("app/assets/js/linq-4.0.2.wsh")._default;
|
||||||
|
|
||||||
|
@ -696,8 +695,7 @@ function __main__() {
|
||||||
console.log(" WelsonJS - Build a Windows app on the Windows built-in JavaScript engine");
|
console.log(" WelsonJS - Build a Windows app on the Windows built-in JavaScript engine");
|
||||||
console.log(" C-2021-000237 (cros.or.kr), 10.5281/zenodo.11382385 (doi.org), 2023-A0562 (oss.kr), Codename Macadamia");
|
console.log(" C-2021-000237 (cros.or.kr), 10.5281/zenodo.11382385 (doi.org), 2023-A0562 (oss.kr), Codename Macadamia");
|
||||||
console.log(" This software is distributed as open source under the GPL 3.0 or MS-RL licenses.");
|
console.log(" This software is distributed as open source under the GPL 3.0 or MS-RL licenses.");
|
||||||
console.log(" Please support this project: https://gnh1201.link");
|
console.log(" https://github.com/gnh1201/welsonjs");
|
||||||
console.log(" Source code available: https://github.com/gnh1201/welsonjs");
|
|
||||||
console.log("");
|
console.log("");
|
||||||
|
|
||||||
if (typeof window === "undefined") {
|
if (typeof window === "undefined") {
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
@echo off
|
|
||||||
title Remove Chrome policies created by potentially unwanted programs
|
|
||||||
color 0C
|
|
||||||
|
|
||||||
echo [INFO] This script must be run with administrator privileges.
|
|
||||||
echo [INFO] It will remove Chrome policies, enrollment tokens, forced extensions, and user profiles.
|
|
||||||
echo.
|
|
||||||
|
|
||||||
:: Step 1: Remove policy-related registry keys
|
|
||||||
echo [STEP 1] Removing Chrome policy registry keys...
|
|
||||||
|
|
||||||
reg delete "HKCU\Software\Google\Chrome" /f >nul 2>&1
|
|
||||||
reg delete "HKCU\Software\Policies\Google\Chrome" /f >nul 2>&1
|
|
||||||
reg delete "HKLM\Software\Google\Chrome" /f >nul 2>&1
|
|
||||||
reg delete "HKLM\Software\Policies\Google\Chrome" /f >nul 2>&1
|
|
||||||
reg delete "HKLM\Software\Policies\Google\Update" /f >nul 2>&1
|
|
||||||
reg delete "HKLM\Software\WOW6432Node\Google\Enrollment" /f >nul 2>&1
|
|
||||||
|
|
||||||
:: Step 2: Remove CloudManagementEnrollmentToken value only
|
|
||||||
echo [STEP 2] Removing CloudManagementEnrollmentToken value...
|
|
||||||
|
|
||||||
reg delete "HKLM\Software\WOW6432Node\Google\Update\ClientState\{430FD4D0-B729-4F61-AA34-91526481799D}" /v CloudManagementEnrollmentToken /f >nul 2>&1
|
|
||||||
|
|
||||||
:: Step 3: Remove policy-enforced extension installations
|
|
||||||
echo [STEP 3] Removing extension force-install policies...
|
|
||||||
|
|
||||||
reg delete "HKCU\Software\Policies\Google\Chrome\ExtensionInstallForcelist" /f >nul 2>&1
|
|
||||||
reg delete "HKLM\Software\Policies\Google\Chrome\ExtensionInstallForcelist" /f >nul 2>&1
|
|
||||||
|
|
||||||
:: Step 4: Remove Chrome policy directories
|
|
||||||
echo [STEP 4] Removing Chrome policy directories...
|
|
||||||
|
|
||||||
if exist "%ProgramFiles(x86)%\Google\Policies" (
|
|
||||||
rmdir /s /q "%ProgramFiles(x86)%\Google\Policies"
|
|
||||||
)
|
|
||||||
|
|
||||||
if exist "%ProgramFiles%\Google\Policies" (
|
|
||||||
rmdir /s /q "%ProgramFiles%\Google\Policies"
|
|
||||||
)
|
|
||||||
|
|
||||||
if exist "%ProgramData%\Google\Policies" (
|
|
||||||
rmdir /s /q "%ProgramData%\Google\Policies"
|
|
||||||
)
|
|
||||||
|
|
||||||
:: Step 5: Remove entire user Chrome profile
|
|
||||||
echo [STEP 5] Removing entire Chrome user profile directory...
|
|
||||||
echo This includes all settings, cache, cookies, history, saved logins, extensions, etc.
|
|
||||||
|
|
||||||
RD /S /Q "%LocalAppData%\Google\Chrome"
|
|
||||||
|
|
||||||
echo.
|
|
||||||
echo [COMPLETE] Chrome has been fully reset and cleaned.
|
|
||||||
echo Restart Chrome or reboot the system to apply all changes.
|
|
||||||
pause
|
|
35
app/assets/img/CSDN_Logo.svg
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
height="113.54473"
|
||||||
|
width="500"
|
||||||
|
version="1.1"
|
||||||
|
id="svg2"
|
||||||
|
viewBox="0 0 500 113.54473">
|
||||||
|
<metadata
|
||||||
|
id="metadata12">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<defs
|
||||||
|
id="defs10" />
|
||||||
|
<path
|
||||||
|
style="fill:#262626"
|
||||||
|
id="path4"
|
||||||
|
d="m 129.51179,83.4172 c 9.30714,3.40291 28.7193,6.78583 44.41737,6.78583 16.91482,0 26.32967,-4.68345 27.08366,-11.95203 0.68617,-6.6303 -6.23934,-7.5279 -25.34032,-12.05181 C 149.279,59.72847 132.43997,49.71122 134.09156,33.70198 136.01044,15.11563 160.884,1.06914 199.05006,1.06914 c 18.6063,0 36.64612,1.3125 45.99316,4.37631 l -3.20744,23.4374 c -6.06779,-2.11036 -29.29376,-5.04253 -45.0038,-5.04253 -15.92945,0 -24.17542,5.01062 -24.7459,10.50395 -0.71808,6.95343 7.55981,7.27656 28.25254,12.78585 28.02116,7.10901 40.27243,17.11828 38.66872,32.63683 -1.87898,18.25528 -24.25921,33.77778 -68.94785,33.77778 -18.60231,0 -34.63549,-3.3949 -43.4679,-6.7899 L 129.5078,83.42119 Z M 392.11041,6.89758 c 101.74823,-19.18476 110.52878,15.28717 107.38518,45.78969 l -5.92418,56.42926 -32.29773,0 5.40556,-51.46651 c 1.16888,-11.33373 8.44544,-33.50252 -26.68473,-32.67273 -12.15952,0.29521 -18.18742,1.96275 -18.18742,1.96275 0,0 -1.05718,13.69542 -2.33776,23.81639 l -6.12364,58.3601 -31.6754,0 6.28721,-57.51835 4.15291,-44.7006 z M 263.59766,4.2287 c 7.2606,-0.78989 18.41481,-1.59174 33.76581,-1.59174 25.62755,0 46.34821,4.46008 59.17794,13.83903 11.52123,8.74465 19.18875,22.90283 17.06642,43.41604 -1.95877,19.08902 -11.88426,32.4533 -26.33367,40.7192 -13.22069,7.7952 -29.88019,11.1263 -54.93327,11.1263 -14.77255,0 -28.86291,-0.7978 -39.57829,-2.3856 L 263.60165,4.2287 Z m 21.17544,84.22704 c 2.4694,0.47872 5.71673,0.95345 12.11963,0.95345 25.63553,0 43.71125,-12.59835 45.5264,-30.31104 2.63696,-25.60361 -13.39622,-34.5557 -40.40807,-34.40012 -3.49866,0 -8.36167,0 -10.9348,0.47074 l -6.30715,63.28298 z" />
|
||||||
|
<path
|
||||||
|
style="fill:#ca0c16"
|
||||||
|
id="path6"
|
||||||
|
d="m 111.14086,109.99823 c -6.07577,2.1063 -18.662147,3.5425 -36.247187,3.5425 -50.56893,0 -77.8640296,-23.7366 -74.63664955,-55.11678 C 4.1187134,21.03581 44.554713,0 88.828463,0 105.97466,0 116.07169,1.38031 125.53043,3.69413 l -3.03589,25.18872 c -6.2912,-2.11834 -21.03582,-4.06514 -32.971937,-4.06514 -26.05042,0 -48.17532,7.75928 -50.71255,32.30572 -2.26196,21.94937 13.26856,32.4413 42.57429,32.4413 10.20075,0 25.240577,-1.46005 32.194007,-3.57042 l -2.43749,24.00392 z" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.9 KiB |
17
app/assets/img/Fediverse_logo_proposal.svg
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="196.52mm" height="196.52mm" viewBox="0 0 196.52 196.52">
|
||||||
|
<path fill="#a730b8" d="M47.9242 72.7966a18.2278 18.2278 0 0 1-7.7959 7.7597l42.7984 42.9653 10.3182-5.2291zm56.4524 56.6704-10.3182 5.2291 21.686 21.7708a18.2278 18.2278 0 0 1 7.7975-7.7608z"/>
|
||||||
|
<path fill="#5496be" d="M129.6645 102.0765l1.7865 11.4272 27.4149-13.8942a18.2278 18.2278 0 0 1-4.9719-9.8124zm-14.0658 7.1282-57.2891 29.0339a18.2278 18.2278 0 0 1 4.9728 9.8133l54.1027-27.4194z"/>
|
||||||
|
<path fill="#ce3d1a" d="M69.5312 91.6539l8.1618 8.1933 29.269-57.1387a18.2278 18.2278 0 0 1-9.787-5.0219zm-7.1897 14.0363-14.0022 27.3353a18.2278 18.2278 0 0 1 9.786 5.0214l12.3775-24.1639z"/>
|
||||||
|
<path fill="#d0188f" d="M39.8906 80.6763a18.2278 18.2278 0 0 1-10.8655 1.7198l8.1762 52.2981a18.2278 18.2278 0 0 1 10.8645-1.7198z"/>
|
||||||
|
<path fill="#5b36e9" d="M63.3259 148.3109a18.2278 18.2278 0 0 1-1.7322 10.8629l52.2893 8.3907a18.2278 18.2278 0 0 1 1.7322-10.8629z"/>
|
||||||
|
<path fill="#30b873" d="M134.9148 146.9182a18.2278 18.2278 0 0 1 9.788 5.0224l24.1345-47.117a18.2278 18.2278 0 0 1-9.7875-5.0229z"/>
|
||||||
|
<path fill="#ebe305" d="M126.1329 33.1603a18.2278 18.2278 0 0 1-7.7975 7.7608l37.3765 37.5207a18.2278 18.2278 0 0 1 7.7969-7.7608z"/>
|
||||||
|
<path fill="#f47601" d="M44.7704 51.6279a18.2278 18.2278 0 0 1 4.9723 9.8123l47.2478-23.9453a18.2278 18.2278 0 0 1-4.9718-9.8113z"/>
|
||||||
|
<path fill="#57c115" d="M118.2491 40.9645a18.2278 18.2278 0 0 1-10.8511 1.8123l4.1853 26.8 11.42 1.8324zm-4.2333 44.1927 9.8955 63.3631a18.2278 18.2278 0 0 1 10.88-1.6278l-9.355-59.9035z"/>
|
||||||
|
<path fill="#dbb210" d="M49.7763 61.6412a18.2278 18.2278 0 0 1-1.694 10.8686l26.8206 4.3077 5.2715-10.2945zm45.9677 7.382-5.272 10.2955 63.3713 10.1777a18.2278 18.2278 0 0 1 1.7606-10.8593z"/>
|
||||||
|
<path fill="#ffca00" d="M93.4385 23.8419a1 1 0 1 0 33.0924 1.8025 1 1 0 1 0-33.0924-1.8025"/>
|
||||||
|
<path fill="#64ff00" d="M155.314 85.957a1 1 0 1 0 33.0923 1.8025 1 1 0 1 0-33.0923-1.8025"/>
|
||||||
|
<path fill="#00a3ff" d="M115.3466 163.9824a1 1 0 1 0 33.0923 1.8025 1 1 0 1 0-33.0923-1.8025"/>
|
||||||
|
<path fill="#9500ff" d="M28.7698 150.0898a1 1 0 1 0 33.0923 1.8025 1 1 0 1 0-33.0923-1.8025"/>
|
||||||
|
<path fill="#ff0000" d="M15.2298 63.4781a1 1 0 1 0 33.0923 1.8025 1 1 0 1 0-33.0923-1.8025"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.2 KiB |
BIN
app/assets/img/Hackernews_logo.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
app/assets/img/RedSky-logo-web.webp
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
app/assets/img/cover.png
Normal file
After Width: | Height: | Size: 118 KiB |
BIN
app/assets/img/cover_old.jpg
Normal file
After Width: | Height: | Size: 139 KiB |
BIN
app/assets/img/demo-example-2020.png
Normal file
After Width: | Height: | Size: 188 KiB |
BIN
app/assets/img/demo-example-2021-2.png
Normal file
After Width: | Height: | Size: 136 KiB |
BIN
app/assets/img/demo-example-2021.png
Normal file
After Width: | Height: | Size: 405 KiB |
BIN
app/assets/img/github_octocat_logo.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
app/assets/img/logo_oss.gif
Normal file
After Width: | Height: | Size: 4.3 KiB |
1
app/assets/img/morioh.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg class="h-10 w-auto" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 101.14 114.68"><defs><style>.cls-1{fill:#6366f1;}.cls-2{mask:url(#mask);}.cls-3{mask:url(#mask-2);}.cls-4{mask:url(#mask-3);}.cls-5{mask:url(#mask-4);}.cls-6{filter:url(#luminosity-noclip-4);}.cls-7{filter:url(#luminosity-noclip-3);}.cls-8{filter:url(#luminosity-noclip-2);}.cls-9{filter:url(#luminosity-noclip);}</style><filter id="luminosity-noclip" x="34.45" y="-8249.25" width="8" height="32766" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"><feFlood flood-color="#fff" result="bg"></feFlood><feBlend in="SourceGraphic" in2="bg"></feBlend></filter><mask id="mask" x="34.45" y="-8249.25" width="8" height="32766" maskUnits="userSpaceOnUse"><g class="cls-9"></g></mask><filter id="luminosity-noclip-2" x="65.59" y="-8249.25" width="8" height="32766" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"><feFlood flood-color="#fff" result="bg"></feFlood><feBlend in="SourceGraphic" in2="bg"></feBlend></filter><mask id="mask-2" x="65.59" y="-8249.25" width="8" height="32766" maskUnits="userSpaceOnUse"><g class="cls-8"></g></mask><filter id="luminosity-noclip-3" x="58.6" y="-8249.25" width="8" height="32766" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"><feFlood flood-color="#fff" result="bg"></feFlood><feBlend in="SourceGraphic" in2="bg"></feBlend></filter><mask id="mask-3" x="58.6" y="-8249.25" width="8" height="32766" maskUnits="userSpaceOnUse"><g class="cls-7"></g></mask><filter id="luminosity-noclip-4" x="28.15" y="-8249.25" width="8" height="32766" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"><feFlood flood-color="#fff" result="bg"></feFlood><feBlend in="SourceGraphic" in2="bg"></feBlend></filter><mask id="mask-4" x="28.15" y="-8249.25" width="8" height="32766" maskUnits="userSpaceOnUse"><g class="cls-6"></g></mask></defs><path class="cls-1" d="M41.55,4.25c3.6-2,7.66-5.85,12-3.52,14.93,8.43,29.77,17.05,44.6,25.65,3.87,2.07,2.77,7,3,10.59-.21,1.81.46,4.09-1,5.52C91,52.3,80.2,60.47,68.86,67.56c-3.23-1.67-7.17-2.59-10.55-.81-5.57,2.44-7.56,10.29-3.67,15,3.78,5.35,12.7,5.21,16.22-.34,2.2-2.52,1.21-6.14,2.19-9a187,187,0,0,0,28-21.82c0,10.83.09,21.66,0,32.49A5.78,5.78,0,0,1,98,88.38C87.31,94.71,76.43,100.72,65.72,107a151.64,151.64,0,0,1-25.33-31.7c1.49-2.86,2.6-6.24,1.26-9.37-1.83-6.12-10.11-8.81-15.17-4.89-5.08,3.24-5.75,11.19-1.3,15.25,2.56,2.86,6.57,3,10.14,2.86A164,164,0,0,0,60,110.26c-3.8,1.88-8,6.17-12.43,3.64C33.07,105.82,18.8,97.31,4.34,89.12c-1.65-1-3.56-2.07-4-4.11A75.22,75.22,0,0,1,.07,73.88c-.31-1.52,1-2.48,1.85-3.49A159.1,159.1,0,0,1,32.31,46.27c4.13,2.43,9.95,2.58,13.36-1.17A10,10,0,0,0,45,30.53c-4.28-3.89-11.82-2.92-14.86,2-1.86,2.45-1.47,5.61-1.69,8.48C18.49,47.78,8.69,54.87.05,63.31.11,52.52-.08,41.73.13,31,0,28.06,2.68,26.44,4.86,25.19c10.37-5.82,20.61-11.85,31-17.72C46,16.64,54.12,27.74,61.47,39.21c-1.51,2.84-2.65,6.17-1.41,9.35,1.73,5.83,9.29,8.76,14.48,5.55,5.28-2.75,6.79-10.58,2.79-15-2.51-3.23-6.81-4.06-10.66-3.43C59.47,24.33,51.33,13.49,41.55,4.25Z"></path><g class="cls-2"><circle class="cls-1" cx="38.45" cy="38.08" r="4"></circle></g><g class="cls-3"><circle class="cls-1" cx="69.59" cy="45.43" r="4"></circle></g><g class="cls-4"><circle class="cls-1" cx="62.6" cy="75.97" r="4"></circle></g><g class="cls-5"><circle class="cls-1" cx="32.15" cy="69.23" r="4"></circle></g></svg>
|
After Width: | Height: | Size: 3.3 KiB |
BIN
app/assets/img/qiita-logo.png
Normal file
After Width: | Height: | Size: 9.9 KiB |
1
app/assets/img/scrapeops-logo.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg id="Layer_4" data-name="Layer 4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 141.09 184.89"><defs><style>.cls-1{fill:#0d53d7;}</style></defs><path class="cls-1" d="M664.89,596.67c1.12-.11,2.24-.26,3.34-.46a49.91,49.91,0,0,0,41.32-49.15h-91.2A49.88,49.88,0,0,0,568.45,597h91.2A47.74,47.74,0,0,0,664.89,596.67Z" transform="translate(-568.45 -547.06)"/><path class="cls-1" d="M643.08,681.5H599.56a49.89,49.89,0,0,0-28.13,44.9,48.09,48.09,0,0,0,.31,5.54H669.6l1.33-.28a49.91,49.91,0,0,0,38.62-48.61c0-.52,0-1,0-1.55Z" transform="translate(-568.45 -547.06)"/><path class="cls-1" d="M609.76,663.8h99.76a49.91,49.91,0,0,0-41.31-47.61c-1.2-.2-2.41-.37-3.63-.48l.1-.25H568.46A49.89,49.89,0,0,0,609.76,663.8Zm26.39-42.47c-1.08.58-2.13,1.19-3.16,1.84C634,622.52,635.07,621.91,636.15,621.33ZM616.67,640a49.59,49.59,0,0,1,4.16-6c.76-.94,1.55-1.86,2.38-2.74s1.69-1.74,2.58-2.57,1.81-1.61,2.75-2.37c-.94.76-1.86,1.55-2.75,2.37s-1.75,1.68-2.58,2.57-1.62,1.8-2.38,2.74a49.59,49.59,0,0,0-4.16,6c-.62,1-1.2,2.12-1.74,3.22C615.47,642.13,616.05,641.06,616.67,640Z" transform="translate(-568.45 -547.06)"/></svg>
|
After Width: | Height: | Size: 1.1 KiB |
BIN
app/assets/img/screenshot.png
Normal file
After Width: | Height: | Size: 122 KiB |
BIN
app/assets/img/screenshot2.png
Normal file
After Width: | Height: | Size: 80 KiB |
BIN
app/assets/img/screenshot3.png
Normal file
After Width: | Height: | Size: 103 KiB |
BIN
app/assets/img/screenshot4.png
Normal file
After Width: | Height: | Size: 224 KiB |
BIN
app/assets/img/screenshot5.png
Normal file
After Width: | Height: | Size: 599 KiB |
BIN
app/assets/img/screenshot6.png
Normal file
After Width: | Height: | Size: 122 KiB |
1
app/assets/img/searchapi-logo.svg
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
app/assets/img/signpath_logo.png
Normal file
After Width: | Height: | Size: 9.3 KiB |
BIN
app/assets/img/structure.png
Normal file
After Width: | Height: | Size: 69 KiB |
BIN
app/assets/img/thanks.png
Normal file
After Width: | Height: | Size: 217 KiB |