Compare commits

...

1308 Commits

Author SHA1 Message Date
fc31b528da
Merge pull request #253 from gnh1201/dev
Some checks are pending
CodeQL / Analyze (javascript) (push) Waiting to run
Merge pull request #252 from gnh1201/master
2025-05-12 02:31:38 +09:00
718dd77c1b
Merge pull request #252 from gnh1201/master
Update commit history to the dev branch
2025-05-12 02:30:34 +09:00
e1cb460649
Merge pull request #248 from baramofme/master
Fix Gemini llm call
2025-05-12 02:25:56 +09:00
Jihoon Yi
99dc2d321c
Merge branch 'gnh1201:master' into master 2025-05-11 14:28:09 +09:00
0ccddd4e75
Merge pull request #249 from gnh1201/dev
Some checks are pending
CodeQL / Analyze (javascript) (push) Waiting to run
Improve the concept to access a blob sources
2025-05-11 01:30:30 +09:00
5087359ac3 Revert "Replace the keyword void to Task for async method"
This reverts commit 0ad978bb6b.
2025-05-11 01:21:08 +09:00
1ab70d7cd7 Revert "Update CDN servers list"
This reverts commit 0438ee9a50.
2025-05-11 01:05:09 +09:00
0438ee9a50 Update CDN servers list 2025-05-10 21:31:49 +09:00
Jihoon Yi
90ea515f41
Update winservice.js
fix wrong typo
2025-05-10 20:51:17 +09:00
Jihoon Yi
2bff4df4be
Update security.js
fix wrong typo
2025-05-10 20:50:24 +09:00
Jihoon Yi
10606532cb
Update testloader.js
Add missing closing brackets in test_implementsobject
2025-05-10 18:38:45 +09:00
0ad978bb6b Replace the keyword void to Task for async method 2025-05-10 16:53:47 +09:00
Jihoon Yi
452675273b
Update language-inference-engine.js 2025-05-10 16:36:53 +09:00
Jihoon Yi
d8a29eaeee
Update language-inference-engine.js
- Add response type check before parsing
- Wrap JSON.parse in a try/catch to handle potential malformed responses.
- Use “system” role for the initial bias message on gemini model object's wrap
2025-05-10 16:30:46 +09:00
Jihoon Yi
b1078cd36c
Add missing model selection in honoai_gemini.ai.js
Add missing model selection
2025-05-10 16:22:08 +09:00
a001471451 Improve the concept to access a blob sources 2025-05-10 16:07:36 +09:00
Jihoon Yi
bcdfef3f6f
Create honoai_gemini.ai.js
Add honoi ai call with gemini
2025-05-10 15:54:04 +09:00
Jihoon Yi
ef23e41e3a
Update language-inference-engine.js
Fix gemini call broken
2025-05-10 15:50:55 +09:00
5f10d50a3c
Create clean_chrome_pup.bat
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled
2025-05-08 22:31:55 +09:00
aee5fb22d0
Merge pull request #245 from gnh1201/dev
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled
Add JavaScript CDN servers
2025-05-05 23:44:59 +09:00
14c8b12df7 Add a CDN servers 2025-05-05 23:32:41 +09:00
deed89560b Update ResourceServer.cs 2025-05-05 23:22:02 +09:00
eb32437f96 Update ResourceServer.cs 2025-05-05 21:34:50 +09:00
c95b7a373b Update ResourceServer.cs 2025-05-05 21:33:06 +09:00
302e7ce4fc Add an available CDN servers 2025-05-05 19:13:41 +09:00
a5fc5de78f Update ResourceServer.cs 2025-05-05 17:47:50 +09:00
d362d852ad Add JavaScript CDN servers 2025-05-05 17:38:48 +09:00
2a3f9fb4fa
Update README.md
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled
2025-05-01 14:32:48 +09:00
944751121c
Merge pull request #243 from gnh1201/dev
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled
Add the example to use function calling on LLM
2025-04-27 13:14:27 +09:00
fb420d1116 Add the example to use function calling on LLM 2025-04-27 13:09:03 +09:00
26af578178
Merge pull request #242 from gnh1201/dev
Set throttle to the prompt context
2025-04-27 11:43:52 +09:00
245dd85341 Update editor.html 2025-04-27 11:39:43 +09:00
fb6596fe64 Update editor.html 2025-04-27 11:10:00 +09:00
a42180d244 Set throttle to the prompt context 2025-04-27 10:50:52 +09:00
73b24f9a56
Merge pull request #240 from gnh1201/dev
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled
Fix bug when use DevTools CORS policy (WebSocket error)
2025-04-22 21:31:37 +09:00
eae2795bbf Update Program.cs 2025-04-22 21:27:23 +09:00
98e73b2372 Fix bug when use the devtools protocol with the remote allow origins (Fix WebSocket error) 2025-04-22 21:26:42 +09:00
2225ab9011
Merge pull request #239 from gnh1201/dev
Improve WelsonJS Editor with React framework
2025-04-18 19:51:56 +09:00
4c0895850b Update the integrity attributes 2025-04-18 19:48:41 +09:00
ea412908ef Update editor.html 2025-04-18 19:31:23 +09:00
05ea48a0be some updates 2025-04-18 19:22:25 +09:00
243ff95198 Migrate to React framework 2025-04-18 01:06:27 +09:00
8341394912
Merge pull request #238 from gnh1201/dev
Forward Whois and DNS query data to LLM services
2025-04-12 14:34:59 +09:00
e5a89c9182 Forward Whois and DNS query data to LLM services
Forward Whois and DNS query data to LLM services (e.g. Server configuration assistant)
2025-04-12 14:24:59 +09:00
df5b8cd9f0
Merge pull request #237 from gnh1201/dev
Add support the Azure AI, Optimize the HTTPClient object uses.
2025-04-11 14:19:55 +09:00
e7b6a87175 Reduce code complexity 2025-04-11 14:15:03 +09:00
5b2863058a Add support the Azure AI, Optimize the HTTPClient object uses. 2025-04-11 13:44:21 +09:00
cd8844afef
Merge pull request #236 from gnh1201/dev
Update the markdown files
2025-04-10 16:34:47 +09:00
b26d979b8d Update the markdown files 2025-04-10 16:12:43 +09:00
5446a1bee0
Update README.md
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2025-04-10 15:56:18 +09:00
10101986be
Update README.md
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2025-04-10 15:56:09 +09:00
47a5f50712
Update README.md
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2025-04-10 15:56:01 +09:00
86517f313c
Update README.md
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2025-04-10 15:55:48 +09:00
b6d34404b5 Update README.md 2025-04-10 13:50:37 +09:00
88ac0cd31e Update README.md 2025-04-10 13:41:57 +09:00
3e0fd7c532 Update README.md, SECURITY.MD 2025-04-10 13:39:23 +09:00
22d10cd28b
Merge pull request #235 from gnh1201/dev
Update SECURITY.MD
2025-04-10 13:29:19 +09:00
0e95b72b21 Update SECURITY.MD 2025-04-10 13:23:16 +09:00
426a9d7721
Merge pull request #234 from gnh1201/dev
Update 2025-04-10
2025-04-10 02:29:10 +09:00
d42210f922
Update WelsonJS.Toolkit/WelsonJS.Launcher/Program.cs
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-04-10 02:27:42 +09:00
e853003bda
Merge branch 'master' into dev 2025-04-10 02:26:21 +09:00
8ca4faa88a
Update README.md
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
2025-04-10 02:23:24 +09:00
f84f2195c3 Revert Cache Compression 2025-04-10 02:12:28 +09:00
1742ca385b Update AzureAi.cs 2025-04-10 02:00:18 +09:00
2a9ebaff51 Update AzureAi.cs 2025-04-10 01:48:33 +09:00
916154499c Some updates 2025-04-09 19:58:41 +09:00
53a84b2349 Update README.md 2025-04-07 14:45:25 +09:00
6e3eb5c1d3 Update README.md 2025-04-07 14:44:03 +09:00
4b4754ae16 Update README.md 2025-04-07 14:43:27 +09:00
a273d6aac6 Update README.md 2025-04-07 14:41:56 +09:00
9e1878628b Update README.md 2025-04-07 14:33:47 +09:00
04ce7fdae5 Update README.md, SECURITY.MD 2025-04-07 14:31:11 +09:00
f7de7bd430 Add Cache Compression 2025-04-06 15:23:19 +09:00
ab8a864519
Update README.md 2025-04-05 23:32:10 +09:00
427f8dded0
Update README.md 2025-04-05 23:24:54 +09:00
a96764f725
Update README.md 2025-04-05 23:24:17 +09:00
46d0244c34
Merge pull request #221 from gnh1201/dev
Add the cached blob #220
2025-04-05 20:13:40 +09:00
2cb3c1c331 Add the cached blob 2025-04-05 20:05:23 +09:00
231e6a56bd
Merge pull request #219 from gnh1201/dev
Change the remote blob server to localhost
2025-04-05 17:47:25 +09:00
295ad2fca8 Update ResourceServer.cs 2025-04-05 17:43:34 +09:00
9ecc93a399 Update ResourceServer.cs 2025-04-05 17:42:44 +09:00
2896cc6bf1 Some updates 2025-04-05 17:27:38 +09:00
be37951807 Add the blob server gateway 2025-04-05 17:10:19 +09:00
d38e26ba67
Merge pull request #218 from gnh1201/dev
Refactor an endpoints of the web based editor
2025-04-05 15:24:50 +09:00
dd85e98c9a Some updates 2025-04-05 15:16:15 +09:00
d8fa8779de Refactor an endpoints of the web based editor 2025-04-05 12:53:28 +09:00
f6fd43ae50
Merge pull request #214 from gnh1201/dev
Add Azure AI service (Azure AI Foundry), Add the AppConfig manager
2025-04-02 11:34:00 +09:00
96dbe7b2cd Add Azure AI service (Azure AI Foundry), Add the AppConfig manager 2025-04-02 11:25:23 +09:00
c1fe39d3cc
Merge pull request #213 from gnh1201/dev
Adapt a code review, SRI, CORS, etc.
2025-03-31 17:41:01 +09:00
56ee12741c some updates 2025-03-31 17:09:28 +09:00
4372bdb09d some updates 2025-03-31 16:59:56 +09:00
b21f967a6a Update bootstrap.bat 2025-03-31 16:31:07 +09:00
40b0b704e3 some updates 2025-03-31 15:06:03 +09:00
9a8ee4d7f9 some updates 2025-03-31 14:50:02 +09:00
4f319d474f some updates 2025-03-31 14:18:03 +09:00
93ed60bcf7 some updates 2025-03-31 14:16:35 +09:00
5d717505f4 Edit the codes from code review result 2025-03-30 22:24:35 +09:00
b0e50d33bc Merge branch 'dev' of https://github.com/gnh1201/welsonjs into dev 2025-03-30 21:12:10 +09:00
c0f9816000 Update editor.html 2025-03-30 20:50:54 +09:00
00ea473683 set SRI and CORS policy strictly to editor.html 2025-03-30 20:48:03 +09:00
7e9054fb8f
Merge pull request #203 from gnh1201/dev
Revert "Reduce SAS token period to 2 years"
2025-03-27 18:02:51 +09:00
f29a63027f Revert "Reduce SAS token period to 2 years"
This reverts commit e930cf86fd.
2025-03-27 17:55:13 +09:00
3419e62c6a
Merge pull request #202 from gnh1201/dev
Change the blob download server
2025-03-27 17:50:53 +09:00
e930cf86fd Reduce SAS token period to 2 years 2025-03-27 17:42:58 +09:00
c0a27efd8d Update bootstrap.bat 2025-03-27 17:35:10 +09:00
d42539c0a8
Update README.md 2025-03-26 11:44:37 +09:00
8389f755fd
Merge pull request #200 from gnh1201/dev
Update the assembly info
2025-03-23 16:02:36 +09:00
6d5af6d422 Update the assembly info 2025-03-23 15:55:45 +09:00
7738b3b898
Merge pull request #199 from gnh1201/dev
Add the mutex to avoid redundant
2025-03-23 15:31:28 +09:00
c1052e0147 Code consistency fix, Replace Random to RandomNumberGenerator, Mutex dispose 2025-03-23 15:12:15 +09:00
d3135bef8e Add the mutex to avoid redundant 2025-03-23 14:43:23 +09:00
54af38b6b6 Add TFA (TOTP) endpoint 2025-03-21 23:50:22 +09:00
9d4b7e535c
Merge pull request #198 from gnh1201/dev
Update setup.iss
2025-03-21 19:51:01 +09:00
8190c80f1a Update setup.iss 2025-03-21 19:39:28 +09:00
c887e1914d
Merge pull request #197 from gnh1201/dev
Update in 2025-03-21
2025-03-21 17:25:45 +09:00
394ce1e903 Update in 2025-03-21 2025-03-21 17:18:39 +09:00
d2cba59b6b Update in 2025-03-21
1. Remove PHP asset files. (Moved to github.com/gnh1201/caterpillar)
2. Add `ARM64` architecture support to lib/python3.js and lib/http.js files.
3. Update the installer profile
2025-03-21 12:03:12 +09:00
7a23340623
Merge pull request #196 from gnh1201/dev
Update http.js
2025-03-21 10:47:13 +09:00
5a2a48945b Update http.js 2025-03-21 10:26:54 +09:00
51da417506 Update http.js 2025-03-20 17:03:31 +09:00
a148319b44
Merge pull request #195 from gnh1201/dev
Update setup.iss
2025-03-20 13:24:31 +09:00
340794d14c Update setup.iss 2025-03-20 13:14:01 +09:00
f6b222e469
Merge pull request #194 from gnh1201/dev
Update the installer profile, Dns Query, and namespaces
2025-03-20 11:29:15 +09:00
fb17f37188 Update setup.iss 2025-03-20 11:15:37 +09:00
2450bc0b9c Update ResourceServer.cs 2025-03-20 11:02:33 +09:00
6737b4885b Update DnsQuery.cs 2025-03-20 10:11:29 +09:00
81d6e67f94 Update the namespaces 2025-03-20 09:42:38 +09:00
911be8135c
Merge pull request #193 from gnh1201/dev
Add DNS Query feature
2025-03-19 17:10:42 +09:00
e68c1e5e2f Add DNS Query feature 2025-03-19 17:03:06 +09:00
07e0665275
Merge pull request #192 from gnh1201/dev
Improve initial warming up time, and add WHOIS request feature
2025-03-19 16:02:23 +09:00
4e78905bbc Enhance a performance and security in PR 2025-03-19 15:48:12 +09:00
e2c9169121 Update editor.html, ResourceServer.cs 2025-03-19 14:02:12 +09:00
1f859c75c6 Improve initial start time, and Add WHOIS request 2025-03-19 12:10:00 +09:00
b2fdc38790
Merge pull request #191 from gnh1201/dev
Minor fixes
2025-03-17 17:53:41 +09:00
07991329fc Update editor.html 2025-03-17 17:47:44 +09:00
5cea33ec20
Merge pull request #190 from gnh1201/dev
Minor fixes
2025-03-17 17:40:37 +09:00
01e94830e7 Update editor.html 2025-03-17 17:23:55 +09:00
c8e757487e Update editor.html 2025-03-17 17:19:05 +09:00
9cd4f2d744
Merge pull request #189 from gnh1201/dev
Minor fixes for the context menus
2025-03-17 17:02:32 +09:00
2a2cdf8a4a Update MainForm.cs 2025-03-17 16:49:04 +09:00
4a46d6211c
Merge pull request #188 from gnh1201/dev
One more fixes for #187
2025-03-17 14:01:27 +09:00
98b9019633 Update editor.html 2025-03-17 13:54:38 +09:00
434f5d4a8d Update editor.html 2025-03-17 13:49:23 +09:00
46a3049d62 Update editor.html 2025-03-17 13:29:00 +09:00
be9ed37eea Update editor.html 2025-03-17 13:24:03 +09:00
dd978ab952
Merge pull request #187 from gnh1201/dev
LLM AI based code generation in the code editor
2025-03-17 12:39:46 +09:00
15b2e606b1 Some updates for optimization and security 2025-03-17 11:09:00 +09:00
0cbb22ac26 Add LLM AI code generation 2025-03-16 18:14:02 +09:00
11afb64706
Merge pull request #186 from gnh1201/dev
Update 2025-03-16
2025-03-16 15:50:52 +09:00
240a65e61c Update ResourceServer.cs 2025-03-16 15:37:26 +09:00
2da5051c5b Update ResourceServer.cs 2025-03-16 15:08:20 +09:00
1124dc5bf4 Add a setting to separate web browser user profiles. 2025-03-16 14:28:59 +09:00
b93d16669f Update ExecutablesCollector.cs 2025-03-16 04:33:39 +09:00
5ab1c97b79
Merge pull request #185 from gnh1201/dev
Add the code completion with Monaco Editor #183
2025-03-16 03:44:02 +09:00
0aceb0e86b Update ResourceServer.cs 2025-03-16 03:30:15 +09:00
dc06506276 Add the code completion with Monaco Editor #183
This update supports the ability to auto-completion executable file paths in the code editor through the list of software installed on the local computer.
2025-03-16 03:11:59 +09:00
7947d91c3a
Merge pull request #184 from gnh1201/dev
Add some code for #183 (Auto completion)
2025-03-15 00:55:40 +09:00
1f2a1e79b7 Update ResourceServer.cs 2025-03-15 00:46:07 +09:00
6722704859 Update ResourceServer.cs 2025-03-15 00:37:03 +09:00
96bd29c06a Adopt the comments of the AI reviewers 2025-03-15 00:23:20 +09:00
c6240fb793
Update codeql-analysis.yml 2025-03-15 00:13:02 +09:00
74ca7dcd6c
Update llm-code-review.yml 2025-03-15 00:12:27 +09:00
b1cabe9fbb Add some code for #183 2025-03-15 00:07:28 +09:00
6bb1dcc3f1
Merge pull request #182 from gnh1201/dev
Add the notify (tray) icon to Launcher
2025-03-14 17:59:20 +09:00
b3f75d3c53 Fix status code 2025-03-14 17:55:05 +09:00
4d26f504f8 Merge branch 'dev' of https://github.com/gnh1201/welsonjs into dev 2025-03-14 17:47:15 +09:00
4bc2a95c42 Add the notify (tray) icon to Launcher
Add the notify (tray) icon to Launcher
2025-03-14 17:46:38 +09:00
c382ffbf46
Update README.md
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-03-12 16:12:15 +09:00
6fa4f64e0b
Merge pull request #181 from gnh1201/dev
AI code review workflow test #180
2025-03-12 15:50:25 +09:00
6d601aa79f Update editor.html 2025-03-12 15:47:12 +09:00
4105b567ee Update editor.html 2025-03-12 15:03:43 +09:00
4fbd0970ed
Update llm-code-review.yml
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2025-03-11 14:54:29 +09:00
be782c1ebd Update codeql-analysis.yml 2025-03-10 10:43:21 +09:00
1982b0fc6b Update README.md 2025-03-10 10:28:08 +09:00
ff88f484f6
Update llm-code-review.yml
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2025-03-10 10:02:03 +09:00
e5c970bea1
Create llm-code-review.yml 2025-03-10 09:59:56 +09:00
653c44dbf6
Merge pull request #179 from gnh1201/dev
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Add the favicon.ico response when try a request
2025-03-10 00:33:14 +09:00
9213d18c90 Reduce complexity: Splitting the GetResource method into separate methods 2025-03-10 00:16:42 +09:00
7c19dd366f Add the favicon.ico response when try a request 2025-03-09 23:56:38 +09:00
39c1fbb29b
Update README.md 2025-03-09 18:44:03 +09:00
53124007c2
Update editor.html 2025-03-09 18:01:12 +09:00
fdc6062433
Update editor.html 2025-03-09 17:50:17 +09:00
bb3cd40012
Add the Monaco Editor to WelsonJS Launcher #137
Update editor.html
2025-03-09 17:17:54 +09:00
e9c6a493eb Add the Monaco Editor to WelsonJS Launcher #137
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2025-03-08 22:52:45 +09:00
24ba77d1f6
Update README.md
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-03-04 16:52:10 +09:00
a3c26a202d
Update README.md 2025-03-04 16:50:06 +09:00
e9a6e414c1
Update README.md 2025-03-04 16:49:51 +09:00
aa5f3c9b6c Add discord chat link
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-02-28 10:56:47 +09:00
1cf0a8920a Update README.md
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-02-26 22:16:24 +09:00
ba35b022c6 Update README.md 2025-02-26 22:15:29 +09:00
f68c7fd7bd Update README.md 2025-02-26 22:10:11 +09:00
e942f0b9e8 Add the global settings form 2025-02-26 22:01:57 +09:00
ac6cdb0d76
Update README.md
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2025-02-26 13:36:44 +09:00
16723acd97
Update README.md 2025-02-26 13:33:58 +09:00
b31a2d43bb
Update README.md 2025-02-26 13:19:57 +09:00
be6f4b027f
Update README.md 2025-02-26 13:14:18 +09:00
1e93dd22ce
Update README.md 2025-02-26 13:03:04 +09:00
64b2eb0f1b
Update README.md 2025-02-26 13:01:33 +09:00
a80c017206
Update README.md 2025-02-26 12:55:38 +09:00
913eb9f9bf
Update README.md 2025-02-26 12:54:35 +09:00
d9175b83a2
Update README.md 2025-02-26 12:53:06 +09:00
f6d112e38f
Update README.md
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2025-02-25 15:35:54 +09:00
40129f87e3
Update README.md
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-02-23 17:40:10 +09:00
e375ddf6f5 Add the toolstrip menu "Run as Administrator..." 2025-02-23 15:27:09 +09:00
51110e54b7 allow search an instances in the temporary folder
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2025-02-23 03:29:51 +09:00
7d2f76e2dd
Merge pull request #174 from eltociear/patch-1
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
docs: update README.md
2025-02-21 10:30:39 +09:00
Ikko Eltociear Ashimine
5590c81be5
docs: update README.md
minor fix
2025-02-21 03:30:08 +09:00
2c25eb2a43
Update README.md
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2025-02-20 21:49:19 +09:00
ece0054da6 Fix the letter case
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2025-02-20 14:25:39 +09:00
09e9cccc51 Change the toolkit binary download path 2025-02-20 14:19:54 +09:00
85a315eac7 Remove the detect Windows version because of syntax error 2025-02-20 14:11:22 +09:00
3349255d9a Update the .env file location 2025-02-20 13:54:59 +09:00
c4be361f95 Fix instance data survival time issue
The data in the Temp directory has a short retention period, posing a risk of data loss. Therefore, it has been changed to the AppData directory.
2025-02-20 12:57:53 +09:00
432fd39df2 Update bootstrap.bat
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-02-18 12:53:52 +09:00
b31add8d74 Update language-inference-engine.js
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2025-02-15 16:09:39 +09:00
e659c8daf2 Update installService.bat
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-02-11 23:00:27 +09:00
62ab354674 Update installService.bat
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2025-02-11 17:17:51 +09:00
8285825c8b Update test.html 2025-02-11 17:00:43 +09:00
e1ebb0ac2a Update test-oss-korea-2023.json 2025-02-11 16:53:26 +09:00
1aa575b13c Revert "Update test-oss-korea-2023.json"
This reverts commit 0f2e874a4a.
2025-02-11 16:50:42 +09:00
0f2e874a4a Update test-oss-korea-2023.json 2025-02-11 16:40:20 +09:00
c9578ae9f1 Update test.html 2025-02-11 16:36:53 +09:00
a4a7391de6 Fix test page error 2025-02-11 16:35:29 +09:00
495944a3b6
Update router.js 2025-02-11 16:25:13 +09:00
477848b77f Update InstancesForm.Designer.cs
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-02-09 22:42:16 +09:00
a3289cc81d Fix some bugs 2025-02-09 22:05:43 +09:00
4fd38e75c3 Add the list of instances
This commit allows restoring and rerunning previously deployed instances.
2025-02-09 21:41:21 +09:00
5a09d7a79a Add support the Content-Type based URI router
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Add support the Content-Type based URI router
2025-02-08 21:45:43 +09:00
b912ae0b08 Update apikey.json
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2025-02-07 23:47:17 +09:00
eacd68ce88 Update language-inference-engine.js 2025-02-07 23:41:11 +09:00
2251494a48 Update language-inference-engine.js
1. Fix mistypos (e.g.., missing return)
2. Add clovastudio LLM
2025-02-07 23:35:25 +09:00
5b092c7f7a Update README.md
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-02-03 16:42:50 +09:00
4d78bbf31e Update README.md 2025-02-03 16:42:43 +09:00
1c4e607d3d Update README.md 2025-02-03 16:36:03 +09:00
80de6da382 Update README.md 2025-02-03 16:21:51 +09:00
3edff1550c Update README.md 2025-02-03 16:12:21 +09:00
724b89f361 Update README.md 2025-02-03 16:00:03 +09:00
06a09fbc3e
Update language-inference-engine.js
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-01-31 15:55:41 +09:00
2c2696d75f
Update README.md 2025-01-31 13:12:49 +09:00
36d51749b3
Update README.md 2025-01-31 13:10:07 +09:00
ac84bb222d
Update README.md 2025-01-31 13:03:19 +09:00
7c87f25f25
Update README.md 2025-01-31 13:00:20 +09:00
a2123f8765 Update README.md
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2025-01-30 23:39:19 +09:00
2078b45566 Update language-inference-engine.js 2025-01-30 23:33:35 +09:00
a7a00a38d8 Update language-inference-engine.js 2025-01-30 23:28:44 +09:00
a5275388e2 Update language-inference-engine.js 2025-01-30 23:28:28 +09:00
b5704d5746 Update language-inference-engine.js 2025-01-30 23:15:58 +09:00
ee038c6c20 Update README.md
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2025-01-30 19:54:10 +09:00
827dea443c Update README.md 2025-01-30 19:53:39 +09:00
3cf7f6c07c Update language-inference-engine.js 2025-01-30 19:47:30 +09:00
408e98e46b Update README.md 2025-01-30 19:14:11 +09:00
2878eac81d Update README.md 2025-01-30 19:06:47 +09:00
60a26b3ad0 Update language-inference-engine.js 2025-01-30 18:59:04 +09:00
4c8a127ad3 Update language-inference-engine.js 2025-01-30 17:12:22 +09:00
3f993975eb Merge branch 'master' of https://github.com/gnh1201/welsonjs
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2025-01-29 18:41:25 +09:00
68e7e4aec0 Update language-inference-engine.js 2025-01-29 18:24:32 +09:00
e7031baf0b
Update test-oss-korea-2023.json 2025-01-29 18:13:46 +09:00
7d3659ebce Update README.md 2025-01-29 18:07:30 +09:00
a1e254ceb0 Update README.md 2025-01-29 18:06:25 +09:00
0f1c2f3e85 Update README.md 2025-01-29 18:05:35 +09:00
6496da9b7e Update language-inference-engine.js 2025-01-29 17:41:29 +09:00
8699d89694 Update language-inference-engine.js 2025-01-29 17:22:55 +09:00
fb947cc777 Update LIE(Language Inference Engine) integraton of the app.js
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-01-28 09:53:55 +09:00
fe5542a521 Update language-inference-engine.js 2025-01-28 09:46:45 +09:00
47bb893c49 Update language-inference-engine.js 2025-01-28 09:38:23 +09:00
0485412b52 Update apikey.json
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2025-01-28 00:19:06 +09:00
ab2f3df4ea Update language-inference-engine.js 2025-01-28 00:02:22 +09:00
df92b4c58e Create language-inference-engine.js 2025-01-27 23:48:34 +09:00
88e6bd27b2 Change the script URLs
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-01-22 14:28:02 +09:00
b640786f62 Create hanoi.ai.js 2025-01-22 13:55:45 +09:00
1c3a367b18
Update README.md
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-01-20 12:05:41 +09:00
8a2a4c4760 Update chatgpt.js 2025-01-20 10:18:10 +09:00
e585b3e2d4 Update app.js 2025-01-20 10:11:04 +09:00
94601cbf4f Update app.js 2025-01-20 10:06:21 +09:00
905b56beb2 Allow load script from ChatGPT (LLM based AI) service 2025-01-20 10:04:49 +09:00
1337320803
Update README.md
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-01-17 16:17:45 +09:00
1e3389acf4
Update README.md 2025-01-17 14:13:44 +09:00
74005364e2 Add Grok (x.ai) interface 2025-01-17 14:04:35 +09:00
1cea720a70
Update README.md
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-01-15 17:57:15 +09:00
eeb0d0bc19
Update README.md 2025-01-15 17:56:47 +09:00
9d47a18325
Update testloader.js 2025-01-15 16:18:06 +09:00
81f196eed2
Update test-misc.json 2025-01-15 16:09:37 +09:00
8adaf4bdb9
Update test-misc.json 2025-01-15 16:09:26 +09:00
daf7db76b6
Update ovftool.js 2025-01-15 15:38:25 +09:00
38b03fe026 Update shell.js, ovftool.js 2025-01-15 15:18:36 +09:00
e2582447cc Update shell.js 2025-01-15 14:56:14 +09:00
6babec9d6b Update shell.js 2025-01-15 14:56:01 +09:00
a5dce5b55d Update shell.js 2025-01-15 14:42:58 +09:00
babfbe4e38 Update .gitignore 2025-01-15 14:00:57 +09:00
c9f03a5e23 Update shell.js, ovftool.js 2025-01-15 13:58:54 +09:00
f9f35da4d4 Create ovftool.js
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-01-13 15:13:25 +09:00
dd3ebc16df Update the credential management 2025-01-13 14:46:48 +09:00
3120a5ea93
Update README.md 2025-01-13 10:59:45 +09:00
8571ec4d00 Update ip-reputation.js
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2025-01-10 13:29:05 +09:00
1c6d306760 Create lib/ip-reputation.js 2025-01-10 13:28:46 +09:00
9262d83fd5
Update SECURITY.MD 2025-01-09 16:59:31 +09:00
b682f8fc34
Update bootstrap.bat 2025-01-09 16:03:00 +09:00
e1720c5bcf
Update bootstrap.bat 2025-01-09 14:05:48 +09:00
a78581ee69
Update bootstrap.bat 2025-01-09 14:03:13 +09:00
4eb2d4ae06
Update bootstrap.bat 2025-01-09 13:58:48 +09:00
fdd5c74df5
Update README.md 2025-01-09 11:33:35 +09:00
1857712df4
Update README.md 2025-01-09 11:02:08 +09:00
c5ebf36274
Update README.md 2025-01-09 11:01:43 +09:00
8c2d403502
Update README.md 2025-01-08 17:42:29 +09:00
ec92b9605f
Update README.md 2025-01-06 15:06:19 +09:00
c0e8f92e84
Update README.md 2025-01-01 21:19:01 +09:00
fe4d0d562e Add the server-side script files 2025-01-01 21:12:42 +09:00
58e9bdc4ab Add DEFAULT_JSONRPC2_URL variable to lib/jsonrpc2.js 2025-01-01 19:51:11 +09:00
638b172e77 Fix a proxy services and HTTP request issues
1. Separated the data listing available HTTP proxy services into a separate file. (data/available_proxies.json)
2. Excluded the architecture of the user's PC (e.g., 32-bit, 64-bit) from the User-Agent in HTTP requests.
2025-01-01 19:18:40 +09:00
79295de4ce
Update README.md
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-12-30 13:23:16 +09:00
37aa3ea406
Update README.md 2024-12-30 13:22:08 +09:00
1c9e77f890 Create fix_wsh_js_engine_not_found.reg
Fix: Input Error: There is no script engine for file extension ".js".
해결: 입력 오류: 파일 확장자 ".js"에 해당하는 스크립트 엔진이 없습니다.
2024-12-30 13:17:54 +09:00
da153a7900
Update README.md 2024-12-29 06:27:26 +09:00
7903a38f61
Update aviation.js 2024-12-27 15:04:08 +09:00
a99f1c396f
Update testloader.js 2024-12-27 14:55:46 +09:00
5a5526df63
Update anthropic.js 2024-12-27 14:53:17 +09:00
46c5a91032
Update chatgpt.js 2024-12-27 14:52:17 +09:00
e9ba3cff96
Update apikey.json 2024-12-27 14:49:25 +09:00
b4ace286e3
Create apikey.js 2024-12-27 14:49:01 +09:00
7aeb8edfc2
Update apikey.json 2024-12-27 14:34:57 +09:00
31792ebecd
Update apikey.json 2024-12-27 14:33:41 +09:00
7dcd82e7b9
Create apikey.json 2024-12-27 14:33:21 +09:00
fc4d74b7ac
Update std.js 2024-12-27 14:11:15 +09:00
98ff88ffff
Update browser.js 2024-12-27 14:08:56 +09:00
a3fa1a558e Update task-scheduler.js
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-12-22 03:27:35 +09:00
bf6fa1c044 Create task-scheduler.js 2024-12-22 03:26:41 +09:00
8a185cb048 Add a fast-track consultation channels
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-12-20 17:57:44 +09:00
4d6239b606
Merge pull request #168 from chasca8/master
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Update test-oss-korea-2023.json
2024-12-20 15:39:46 +09:00
78445aa4dc
Merge branch 'master' into master 2024-12-20 15:36:56 +09:00
4a9f5a7fd8
Update data/test-oss-korea-2023.json
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2024-12-20 15:20:37 +09:00
e1d2d3e9ff
Update data/test-oss-korea-2023.json
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2024-12-20 15:20:04 +09:00
7ee1e2b745
Update data/test-oss-korea-2023.json
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2024-12-20 15:19:39 +09:00
Scarlet
442d081f9d
Update test-oss-korea-2023.json 2024-12-18 21:26:03 +09:00
Scarlet
36da5ec3a1
Update virustotal.js 2024-12-18 19:07:17 +09:00
Scarlet
f49ba40cb9
Update test-oss-korea-2023.json 2024-12-18 18:20:48 +09:00
a886363603
Merge pull request #166 from gnh1201/revert-165-master
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Revert "Update test-oss-korea-2023.json"
2024-12-18 14:02:57 +09:00
dee6ed1025
Revert "Update test-oss-korea-2023.json" 2024-12-18 14:02:40 +09:00
d8d67ac4c0
Merge pull request #165 from chasca8/master
Update test-oss-korea-2023.json
2024-12-18 13:58:05 +09:00
Scarlet
b400c8d64d
Update test-oss-korea-2023.json 2024-12-17 20:53:53 +09:00
Scarlet
98e2c6c837
Update test-oss-korea-2023.json 2024-12-17 12:03:26 +09:00
a947432134 Update README.md
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-12-12 15:30:22 +09:00
1d0f4172fb Update README.md 2024-12-12 15:28:32 +09:00
06972c2bd1 Update README.md 2024-12-12 15:27:45 +09:00
eccd60c340 Update README.md 2024-12-12 15:26:37 +09:00
c1f9249252 Update aviation.js 2024-12-12 14:36:16 +09:00
c14f4358f3 Add aviation.js, Updatre http.js 2024-12-12 14:22:00 +09:00
2dae3a3abb Update http.js 2024-12-12 13:43:41 +09:00
7d6046624c Update README.md
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-12-11 14:27:28 +09:00
de4016100a Update AnsiX923Padding.cs, PKCS5Padding.cs
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-12-10 18:31:31 +09:00
3ed38eec6a Add error handling flags for AnsiX923Padding, and PKCS5Padding 2024-12-10 17:50:10 +09:00
7ef4437447 Add LEA cryptography algorithm 2024-12-10 16:48:48 +09:00
9c662177ec Update ARIA.cs
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-12-09 17:18:54 +09:00
d6540f1351 Change MD5 to SHA256 in the CreateKey method 2024-12-09 17:17:39 +09:00
1b31859786 Update ARIA.cs 2024-12-09 17:13:58 +09:00
ca857d70eb Update ARIA.cs 2024-12-09 16:55:03 +09:00
eaa52e40a6 Add ARIA cryptography algorithm 2024-12-09 16:50:43 +09:00
5ba8744f6c Update SEED.cs
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-12-06 01:36:31 +09:00
92b3907a8e Clean HIGHT.cs 2024-12-06 00:51:07 +09:00
a95e7e3e0d Update SEED.cs 2024-12-06 00:30:31 +09:00
7a8ef89f09 Update SEED.cs 2024-12-05 18:52:33 +09:00
3b022d68a4 Update SEED.cs 2024-12-05 18:21:21 +09:00
eaa33e3b7b Update SEED.cs 2024-12-05 18:14:24 +09:00
ea78f08710 Update SEED.cs
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-12-05 17:56:11 +09:00
6fa089a854 Update SEED.cs 2024-12-05 17:45:16 +09:00
ba73fddba5 Update SEED.cs 2024-12-05 17:31:21 +09:00
ff0ab03630 Add the SEED cryptography algorithm (Experimental) 2024-12-05 17:24:06 +09:00
7ba17435ac
Update README.md
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-12-04 10:25:20 +09:00
5852e987c6
Update README.md 2024-12-03 19:32:32 +09:00
9b4273e370 Update SECURITY.MD 2024-12-02 19:34:19 +09:00
4e6b9ea086 Update SECURITY.MD 2024-12-02 19:33:10 +09:00
caa56cedb8 Update archive.js 2024-11-29 16:54:53 +09:00
701be4c351 Create archive.js 2024-11-29 16:53:31 +09:00
2ba05aa633 Update lib/punycode.js, lib/totp.js 2024-11-28 21:11:17 +09:00
f00e6eed1e
Update totp.js 2024-11-28 14:13:14 +09:00
81592beb64
Update totp.js 2024-11-28 14:10:28 +09:00
ebdc212afb
Update std.js 2024-11-27 19:26:25 +09:00
b880e7a13d
Update std.js 2024-11-27 19:25:01 +09:00
ce10ac7f7b Update std.js 2024-11-27 16:47:59 +09:00
9012a161c3 Update std.js, README.md, SECURITY.md 2024-11-27 16:45:53 +09:00
9038829f24 Remove the Public API URL
The Public API was proposed for the next version (0.2.7.54), but due to the increased security risks of providing an unauthenticated Public API, the Public API URL is being discontinued.

This service will be available in the future through marketplaces offered by cloud platforms. Additionally, as the server-side script is open-source, you can set it up yourself.

https://github.com/gnh1201/caterpillar
2024-11-27 15:36:35 +09:00
116bd84394
Update totp.js
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-11-26 02:46:06 +09:00
69d7d3c632
Update totp.js 2024-11-26 02:03:15 +09:00
400e904aa9 Update totp.js 2024-11-26 01:49:36 +09:00
27f4dc2084 Update totp.js 2024-11-26 01:42:39 +09:00
2ac75fd24e Add TOTP library 2024-11-26 01:41:21 +09:00
8ddff1cf94 Add the security notice to LLM integration libraries
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-11-25 20:55:47 +09:00
b1428867dc Update the Punycode Public API client 2024-11-25 16:15:14 +09:00
f2044bcfbf Ready use the JSON-RPC 2.0 based stateless proxy
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-11-24 03:15:37 +09:00
b5bc2bd851 Update jsonrpc2.js 2024-11-24 02:20:44 +09:00
b45a7cdd6c Ready use the JSON-RPC 2.0 based stateless proxy 2024-11-23 21:50:32 +09:00
ac31e5e884 Ready use the JSON-RPC 2.0 based stateless proxy 2024-11-23 21:44:03 +09:00
43b5781cbd Ready use the JSON-RPC 2.0 based stateless proxy 2024-11-23 21:26:04 +09:00
3fa72f86d6 Ready use the JSON-RPC 2.0 based stateless proxy 2024-11-23 21:10:06 +09:00
8942a98431 Update http.js 2024-11-23 19:06:43 +09:00
8bb0f68049 Update the search engines 2024-11-23 18:58:29 +09:00
d3743e206c
Update README.md
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-11-20 19:30:27 +09:00
4fe98d32a1
Update README.md 2024-11-20 18:47:20 +09:00
1fc0597f93
Update README.md
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-11-20 01:17:48 +09:00
0f57fba805 Update std.js
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-11-19 17:01:56 +09:00
2f74ceb013
Update README.md
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-11-19 15:31:35 +09:00
009b171946
Update README.md
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-11-18 20:03:16 +09:00
895bfe1ac8
Update README.md 2024-11-18 19:59:04 +09:00
3033382f64
Update README.md 2024-11-18 16:43:10 +09:00
fd21f2faae
Update README.md 2024-11-18 16:40:58 +09:00
5e1f41b48a Update app.js 2024-11-15 05:27:22 +09:00
b98901c75a Update app.js 2024-11-15 05:24:49 +09:00
9b50e5b078 Rename some files 2024-11-15 04:05:06 +09:00
d9ac6d01d0 Update README.md 2024-11-15 03:51:50 +09:00
57fbb16bd8 Add Advanced Mathematics Test 2024-11-15 03:48:19 +09:00
13a8c94bcf Add library numbers 2024-11-15 02:40:58 +09:00
0d6e2076d6
Rename FUNDING.yml to .github/FUNDING.yml 2024-11-13 16:23:47 +09:00
f6b04faea6
Update README.md 2024-11-13 16:06:55 +09:00
eedac13818
Update README.md 2024-11-13 16:03:38 +09:00
d45c21cf24
Delete lib/archive.js 2024-11-13 13:48:16 +09:00
54a1515bcb
Update README.md 2024-11-11 06:12:38 +09:00
4477ef84bf
Update archive.js 2024-11-08 00:07:06 +09:00
4370f40886
Create archive.js 2024-11-08 00:06:33 +09:00
fe2466b49a Update package.json 2024-11-07 23:39:51 +09:00
a8b54493f7
Update app.js 2024-11-06 16:31:37 +09:00
2ee54f77ae
Update FUNDING.yml 2024-11-06 16:21:25 +09:00
187578861b
Update FUNDING.yml 2024-11-06 16:16:27 +09:00
a0420cd10f
Update FUNDING.yml 2024-11-06 16:12:53 +09:00
2f1a0f6e41 Add support the Groq LLM API 2024-11-06 04:17:56 +09:00
6d0a6c645f Add README.md to WelsonJS.Toolkit 2024-11-05 21:03:41 +09:00
55d34f833d Update .appveyor.yml 2024-11-05 20:45:21 +09:00
a0e9a83ddd Update .appveyor.yml 2024-11-05 20:36:30 +09:00
9a35227728 Update WelsonJS.Toolkit.nuspec 2024-11-05 20:35:09 +09:00
af69d66ea9 Update the nuspec file 2024-11-05 20:33:50 +09:00
2487e56847 Merge branch 'master' of https://github.com/gnh1201/welsonjs 2024-11-05 20:01:50 +09:00
5b264b64fd Change the API name DecryptStringHIGHT to DecryptString and EncryptStringHIGHT to EncryptString 2024-11-05 20:01:34 +09:00
ce7a0034be
Update README.md 2024-11-05 14:29:17 +09:00
a8a13b539c Update ScreenMatch.cs 2024-11-04 03:55:11 +09:00
b2975e053c Update ScreenMatch.cs 2024-11-04 03:24:42 +09:00
41fcb8706f Update README.md 2024-11-04 02:22:15 +09:00
3fc6f19227 Update README.md 2024-11-04 02:18:21 +09:00
3e78e0b5d2 Fix bugs related to the settings and logger 2024-11-04 02:04:02 +09:00
020f99c5b2 Update MainForm.cs 2024-11-04 01:22:33 +09:00
3989eeba45 Add Anthropic API integration 2024-11-04 00:32:25 +09:00
412c72f624 Change the application name to lowercase when used in logging 2024-11-02 04:03:01 +09:00
30c0e20eae fix #154 (Migrate parent.Log() to Microsoft.Extensions.Logging)
Migrate parent.Log() to Microsoft.Extensions.Logging
2024-11-02 03:51:07 +09:00
53bc51a3af Update README.md 2024-10-24 23:20:45 +09:00
f95b769f11 Update README.md 2024-10-23 20:55:31 +09:00
5d8e195635 Update README.md 2024-10-23 20:48:11 +09:00
a60d0649c0 Move the images of README.md to ics.catswords.net 2024-10-23 20:45:40 +09:00
377d2bdd71 Update README.md 2024-10-23 18:15:34 +09:00
64fec9583d Remove unnecessary images 2024-10-23 18:08:19 +09:00
9b6637a697 Update README.md 2024-10-23 18:02:35 +09:00
af096d38b8 Update README.md 2024-10-23 18:01:11 +09:00
7eb960c711 Update README.md 2024-10-23 18:00:37 +09:00
a98c1cbc92 Update README.md 2024-10-23 17:58:47 +09:00
53970f97a1 Update README.md 2024-10-23 17:53:59 +09:00
9193df71b7 Merge branch 'master' of https://github.com/gnh1201/welsonjs 2024-10-23 17:53:22 +09:00
d180a01312 add nuget profile, update README.md 2024-10-23 17:53:12 +09:00
7f13b67f70
Update README.md 2024-10-23 15:32:21 +09:00
c9360c6651
Update README.md 2024-10-23 15:31:53 +09:00
489e10b76e
Update README.md 2024-10-22 18:22:48 +09:00
28be18de01 Update ScreenMatch.cs 2024-10-21 04:49:48 +09:00
c03a8011c2 Update ScreenMatch.cs 2024-10-21 04:16:46 +09:00
06731f4d4b Update ServiceMain.cs 2024-10-21 02:16:11 +09:00
44de5bfd1a
Update testloader.js 2024-10-20 00:07:53 +09:00
a00d43a59e
Update ScreenMatch.cs 2024-10-19 23:28:16 +09:00
9783e55069
Update extramath.js 2024-10-19 23:17:34 +09:00
3b101e177e
Update README.md 2024-10-19 21:04:34 +09:00
08b10b4e4a
Update http.js 2024-10-19 20:49:16 +09:00
65d5ee120b
Update README.md 2024-10-18 22:24:55 +09:00
2fc9b11aa6
Update README.md 2024-10-18 21:41:51 +09:00
feb85625c5 Update ScreenMatch.cs
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-10-15 05:22:07 +09:00
e1d4df74b9 Update defaultService.example.js
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-10-15 03:00:06 +09:00
6eaeab5c24 Update the dotnet dependencies 2024-10-15 02:26:35 +09:00
b93c6cd48b fix .env support
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-10-14 04:52:22 +09:00
94afeb406a Add some code to add the .env support
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-10-14 04:38:18 +09:00
9e623b645f
Update README.md
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-10-12 09:41:44 +09:00
4f92b782e9
Update README.md
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-10-08 16:25:59 +09:00
16427b347f
Update README.md 2024-10-08 15:49:22 +09:00
ea6add25ca
Update http.js 2024-10-08 15:24:24 +09:00
89e3704f33 Apply the color level based quantization 2024-10-08 14:59:04 +09:00
736356fe71 Check if the position of a specific template image has changed using previously extracted sample images.
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-10-07 03:39:28 +09:00
89dc45ac7c
Update SECURITY.MD
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-10-07 00:01:38 +09:00
c3d4250094
Update README.md 2024-10-06 22:04:22 +09:00
5357ec167a Update the Thanks to links
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-10-05 19:18:16 +09:00
7824de743f Update screenshot6.png
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-10-04 20:19:34 +09:00
adce996aae Update MainForm.cs 2024-10-04 17:01:02 +09:00
2e334ec12e
Merge pull request #150 from gnh1201/envform
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Add the user variables editor and update related files
2024-10-04 15:11:17 +09:00
641c2070a4 Update MainForm.cs, HeartbeatClient.cs 2024-10-04 15:09:05 +09:00
86916d2ed9 Add --user-variables-file parameter when starting a service 2024-10-03 22:56:04 +09:00
c157116680 Use the user variables in the screen matching feature 2024-10-03 22:27:26 +09:00
1a8c93627a Update EnvForm.cs 2024-10-03 21:23:51 +09:00
ee5f503e42 Add import and export feature 2024-10-03 20:58:42 +09:00
c4c7d5480b Update EnvForm.cs 2024-10-03 20:27:41 +09:00
06cb5095b2 Update the env form 2024-10-03 19:48:05 +09:00
f9ddd3b95e Add the env form 2024-10-03 18:09:14 +09:00
740f392c95
Update README.md
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-10-03 14:40:04 +09:00
be336e6e06 Update the favicon on the launcher app 2024-10-03 14:24:59 +09:00
2318092542 Update README.md 2024-10-03 13:57:09 +09:00
3964f081de Update README.md 2024-10-03 13:56:41 +09:00
ec451f633b Update favicon.ico and related files
New favicon designed by @druidesse
2024-10-03 13:55:26 +09:00
5a7165d142
Update README.md
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-10-02 14:36:47 +09:00
94183f1e60
Update http.js
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-09-28 16:44:43 +09:00
8300e1dba4
Update http.js 2024-09-28 16:44:27 +09:00
d413cb49b4
Update http.js 2024-09-28 16:36:38 +09:00
7babc6bad7
Update http.js 2024-09-28 16:26:47 +09:00
7e3a6bdf45
Update http.js 2024-09-28 16:24:24 +09:00
bd51f1d8e1
Update http.js 2024-09-28 16:23:39 +09:00
fac76f9328 Update README.md 2024-09-27 21:23:48 +09:00
8285eee3c1 Update testloader.js 2024-09-27 21:00:53 +09:00
a36dd8e257 Update lib/http.js, testloader.js 2024-09-27 20:53:29 +09:00
1e7061efae Update README.md 2024-09-27 16:34:13 +09:00
072110f282 Update README.md 2024-09-27 16:32:13 +09:00
3ecd35c4a6 Update README.md 2024-09-27 16:19:33 +09:00
b71366bac7 Add SearchAPI.io to README.MD 2024-09-27 16:17:15 +09:00
c6f614b106 Update testloader.js 2024-09-27 15:55:31 +09:00
a60e7e5d9e fix #145
* Fix #145
* Change the methods and variables `CharsetDetector` to `DetectCharset`
* Add searchapi.io SERP support
2024-09-27 15:53:19 +09:00
ad6cb7e430 Update README.md 2024-09-27 10:46:39 +09:00
e95275fa35 Update README.md 2024-09-27 10:44:26 +09:00
099e95bfd3 Update README.md 2024-09-27 10:22:09 +09:00
3c57828f3a Update README.md 2024-09-27 10:18:32 +09:00
6a4a94f486 Update README.md 2024-09-27 10:06:35 +09:00
27a0a0f5d7 Update README.md 2024-09-27 10:03:38 +09:00
dac6e7c5b1 Update README.md 2024-09-26 20:56:34 +09:00
80450467fc Update README.md 2024-09-26 20:47:00 +09:00
ff3cbd88dd Fix the Tab UI bug, and fix stdout/stderr clear issue 2024-09-26 19:35:43 +09:00
c411f596f9 Update webloader.js and the screenshot 2024-09-26 18:45:23 +09:00
a0933153ba Change the screenshot and the example log message 2024-09-26 18:35:25 +09:00
f03c0ef913 Change the screenshot and add ui components example page 2024-09-26 18:32:38 +09:00
f3a79a3523 Update README.md 2024-09-26 15:49:14 +09:00
f18cf9b859 Add support Tab UI with golden layout 2024-09-26 15:46:07 +09:00
bf66ef6354 Update README.md 2024-09-26 02:00:48 +09:00
330323f0c2 Update testloader.js 2024-09-26 01:26:06 +09:00
b82f00748a
Update README.md 2024-09-25 23:09:31 +09:00
0f7e74a5e2 Update README.md 2024-09-25 22:36:31 +09:00
4db50b12ca Add the partnerships section to README.md 2024-09-25 22:34:25 +09:00
abe59228be fix and test ok #143 2024-09-25 18:21:55 +09:00
3842d1bea8 Update http.js 2024-09-25 16:12:19 +09:00
4f1154f412 Add support ARM architecture (lib/http.js) 2024-09-25 16:11:41 +09:00
ce440ae7f7 Update websocket.js 2024-09-25 16:00:41 +09:00
124ea0ae30 Merge branch 'master' of https://github.com/gnh1201/welsonjs 2024-09-25 15:53:11 +09:00
4327651e1d Update http.js 2024-09-25 15:52:47 +09:00
f1e45f01bb Change the default binary path (lib/http,js, lib/websocket.js) 2024-09-25 15:52:08 +09:00
5e6e3e30ba
Update certchecker.js 2024-09-25 14:46:53 +09:00
266971f5d3 fix #144 2024-09-25 14:12:19 +09:00
ed3b631b30 Update testloader.js 2024-09-25 12:10:47 +09:00
7389131bdc Update README.md 2024-09-23 23:27:06 +09:00
f9302f50ee Update README.md 2024-09-23 23:19:35 +09:00
13bcbbbb15 Update README.md 2024-09-23 23:16:03 +09:00
27f4b24344 Merge branch 'master' of https://github.com/gnh1201/welsonjs 2024-09-23 22:53:40 +09:00
9a7cc6de38 Add the github octocat logo 2024-09-23 22:40:48 +09:00
15e31d60e6
Update README.md 2024-09-23 22:35:46 +09:00
528a9c93a4 Update README.md 2024-09-23 22:34:21 +09:00
7823a0a9b5 Add signpath logo 2024-09-23 22:32:57 +09:00
193fcb16c2
Update README.md 2024-09-23 22:29:45 +09:00
646c4babaa Update .appveyor.yml 2024-09-23 22:21:15 +09:00
f2e62d6602
Update README.md 2024-09-23 02:27:03 +09:00
8d5f88a488 Update MainForm.cs 2024-09-23 02:06:49 +09:00
c7af90896b Update http.js 2024-09-23 01:47:46 +09:00
b3bb9ba28c
Update http.js 2024-09-22 20:59:51 +09:00
54e7bb77f6
Update http.js 2024-09-22 00:15:01 +09:00
78a65f906e
Update http.js 2024-09-22 00:10:04 +09:00
9f8e930a45
Update http.js 2024-09-21 14:22:57 +09:00
5f91e9be12
Update http.js 2024-09-21 14:18:42 +09:00
e575f41a19
Update http.js 2024-09-21 14:14:43 +09:00
13cb1da59d
Update http.js 2024-09-21 14:12:39 +09:00
05874f90e5
Update http.js 2024-09-21 14:08:29 +09:00
25876bd81f Merge branch 'master' of https://github.com/gnh1201/welsonjs
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-09-20 23:41:33 +09:00
96c57b0daa Add keep_headers parameter #143 2024-09-20 23:41:04 +09:00
af395bf4ac
Update README.md #143 2024-09-20 23:27:27 +09:00
611c70a1ff
Update README.md 2024-09-20 23:26:30 +09:00
9730b639b9 Update the proxy API services #143 2024-09-20 23:21:37 +09:00
de6b70a5b1 Add the proxy API services #143 2024-09-20 23:10:30 +09:00
e7f65d50b0 Update ScreenMatch.cs and related files
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-09-20 16:53:50 +09:00
855cf6adef Update defaultService.example.js, .gitignore 2024-09-20 11:50:29 +09:00
5e82c58873 Update defaultService.example.js
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-09-20 10:56:28 +09:00
4b63596c3a Update ServiceMain.cs 2024-09-20 10:50:11 +09:00
8734f3f24a Update ScreenMatch.cs, ServiceMain.cs 2024-09-20 10:32:43 +09:00
c0e42480e0 Update ScreenMatch.cs 2024-09-20 09:36:44 +09:00
0742f17f2a Add the Bitmap Comparison with CRC32 hashing
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-09-19 03:29:43 +09:00
12ce97c385 Update ScreenMatch.cs
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-09-18 15:51:24 +09:00
c36d7fb71f Update ScreenMatch.cs 2024-09-18 15:01:05 +09:00
27e9a328d4 Save file in the droptop coffee 2024-09-18 14:33:15 +09:00
83efe8a156 Create fsm.js
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-09-18 03:32:10 +09:00
ec278ade7b Update .gitignore
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-09-17 23:44:30 +09:00
e38e3fb088 Rename defaultService.js to defaultService.example.js 2024-09-17 23:42:04 +09:00
9cdd9e85ed fix (Happy Chuseok) 2024-09-17 22:22:46 +09:00
775ffb924d
Update SECURITY.MD
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-09-15 23:30:40 +09:00
efd35cd273
Update README.md 2024-09-15 23:29:51 +09:00
4144679db7 Add the event listener onAvScanResult
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-09-15 02:54:18 +09:00
f7b1461cc5 Add to ClamAV integration to the File Event Monitor
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-09-14 22:33:58 +09:00
93ea20cf25 Update settings.example.ini 2024-09-14 20:18:10 +09:00
13d7b821be
Update README.md
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-09-10 14:42:11 +09:00
8db76f49ae Update FileEventMonitor.cs
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-09-09 17:13:07 +09:00
bc74515095 Update FileEventMonitor.cs 2024-09-09 17:10:31 +09:00
672a3637de Add event type: registry modification 2024-09-09 17:09:31 +09:00
91b73186d3 Fix the FileEventMonitor.cs 2024-09-09 16:47:51 +09:00
a18229afea Revert "Update app.js, defaultService.js"
This reverts commit c24166b36d.
2024-09-09 16:42:48 +09:00
c24166b36d Update app.js, defaultService.js 2024-09-09 15:28:33 +09:00
40edee2b83 Remove libyara.NET and a little fixes for sysmon events 2024-09-09 15:26:16 +09:00
671007bb79 Update FileEventMonitor.cs and related files
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-09-09 12:05:39 +09:00
bdee21a66f Update ScreenMatch.cs
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-09-06 17:04:15 +09:00
6f3153a816 Update ScreenMatch.cs, settings.example.ini 2024-09-06 17:03:11 +09:00
a69603a10c Add options to the screen time 2024-09-06 16:42:15 +09:00
28435522de Update ScreenMatch.cs 2024-09-06 16:10:58 +09:00
da08bb7bb9
Merge pull request #139 from soumt-r/grpc_fix
heartbeat grpc service
2024-09-06 15:35:14 +09:00
Soumt
126169e37c fix: fixed heartbeat grpc service 2024-09-06 00:54:00 +09:00
0eb897b07f
Update chrome.js
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-09-04 20:17:55 +09:00
38288153ed Apply Math.Sqrt(templateWidth * templateHeight) < 10.0
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-09-04 17:26:31 +09:00
9227518d1e Update ScreenMatch.cs 2024-09-04 16:20:48 +09:00
bab0a3bba2 Fix STAThreadAttribute issue 2024-09-04 16:18:05 +09:00
85ba0c14be Add the sample_clipboard option to the screen time 2024-09-04 14:12:28 +09:00
ca7b7ad3d5 Update ScreenMatch.cs 2024-09-04 13:26:20 +09:00
87d785df45
Update chrome.js
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-09-04 00:41:01 +09:00
34115728fe
Update chrome.js
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-09-02 21:41:35 +09:00
7ed1cab718
Update chrome.js 2024-09-02 21:14:05 +09:00
ecf12aa83f
Update chrome.js 2024-09-02 21:13:22 +09:00
ffbb560598
Update chrome.js 2024-09-02 20:51:42 +09:00
eb389d34c7
Update chrome.js 2024-09-02 20:51:28 +09:00
c6d55cd1fa Update settings.example.ini
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-09-02 16:03:26 +09:00
db557015fd Update ScreenMatch.cs 2024-09-02 16:01:30 +09:00
2f4b95313f Update ScreenMatch.cs 2024-09-02 15:30:20 +09:00
e70c152494 Add heartbeat.proto 2024-09-02 15:18:15 +09:00
9d7f14cddb Add submodule tessdata 2024-09-02 15:15:38 +09:00
dcdaaa11c2 Add tessdata to the assets 2024-09-02 14:58:05 +09:00
3a1d2ab1ba Update ScreenMatch.cs 2024-09-02 14:37:45 +09:00
ba654438ab Add option ocr128 to the screen time feature 2024-09-02 14:17:06 +09:00
4401ba6847 Remove orphan files 2024-09-02 12:48:07 +09:00
0777faaa5b
Update README.md 2024-09-02 12:39:36 +09:00
577b3f018a
Merge pull request #136 from gnh1201/dependabot/nuget/WelsonJS.Toolkit/WelsonJS.Service/RestSharp-112.0.0
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
Bump RestSharp from 111.4.1 to 112.0.0 in /WelsonJS.Toolkit/WelsonJS.Service
2024-08-30 10:25:10 +09:00
dependabot[bot]
9b5fb5499c
Bump RestSharp in /WelsonJS.Toolkit/WelsonJS.Service
Bumps [RestSharp](https://github.com/restsharp/RestSharp) from 111.4.1 to 112.0.0.
- [Release notes](https://github.com/restsharp/RestSharp/releases)
- [Commits](https://github.com/restsharp/RestSharp/compare/111.4.1...112.0.0)

---
updated-dependencies:
- dependency-name: RestSharp
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-29 19:39:58 +00:00
6ab285bc89 Update testloader.js 2024-08-29 19:59:30 +09:00
af30097c6e Add pegjs test 2024-08-29 19:57:53 +09:00
a0e1e34974 Update README.md 2024-08-29 19:13:52 +09:00
09a472b956 Update README.md 2024-08-29 19:13:12 +09:00
1fec9c1f2a Update README.md 2024-08-29 19:12:26 +09:00
1c4b94faaf Add a parser generator (PEG.js) #135 2024-08-29 19:06:19 +09:00
3602cb4a00 refactor #132 2024-08-29 15:34:54 +09:00
e6fd3a800e Update ServiceMain.cs
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-08-29 11:40:23 +09:00
a8ad7746ee Sometimes we have to destroy everything to solve a problem. #132 2024-08-29 11:17:38 +09:00
4aace2a3ae Update settings.example.ini
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-08-27 01:48:32 +09:00
222fe3c1a0 Read the initial configurations from settings.ini 2024-08-27 01:47:55 +09:00
659fb12db1 Fix typos on FileEventMonitor.cs 2024-08-27 01:24:11 +09:00
8593240692 Use HTTP/1.1 on the gRPC client 2024-08-27 01:16:53 +09:00
34e97347f2 Remove non-free, non-microsoft, and no-updates in uriloader.js 2024-08-27 01:03:24 +09:00
7c0adf8f00 Update ScreenMatch.cs 2024-08-26 21:53:13 +09:00
7b7a25f5e9 Update ServiceMain.cs
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-26 18:29:13 +09:00
4e6b63df50 Update ScreenMatch.cs, ServiceMain.cs 2024-08-26 17:53:21 +09:00
0df9166a13 Update the screen time feature 2024-08-26 15:24:38 +09:00
2db49f85f0 Add method ConvertToBinary to the screen time feature
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-26 01:23:02 +09:00
4947151d00 Update FileEventMonitor.cs 2024-08-25 23:22:52 +09:00
44d7d431e3 Revert "Update app.js, defaultService.js"
This reverts commit c208e6dc6c.
2024-08-25 23:21:58 +09:00
72f70d990d Update FileEventMonitor.cs 2024-08-25 23:16:21 +09:00
1f2f940374 Update .gitignore 2024-08-25 23:10:43 +09:00
c208e6dc6c Update app.js, defaultService.js 2024-08-25 23:08:46 +09:00
0eceab3d9b Add option of the interactive service application 2024-08-25 23:04:34 +09:00
f4703ef7a0 Delete 2024-07-29 19 56 13.png 2024-08-25 22:49:26 +09:00
50d1c93f94 Update settings.example.ini 2024-08-25 22:45:25 +09:00
ecfbf7032b Update .gitignore 2024-08-25 22:44:24 +09:00
d9bdd5c578 Update ScreenMatch.cs 2024-08-25 22:43:34 +09:00
277eb08cba Update ScreenMatch.cs
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-25 18:07:31 +09:00
18e81f71ba Use backward search in the screen time 2024-08-25 17:57:22 +09:00
82ac8e5d02 Fix the argument passing convention 2024-08-25 15:28:03 +09:00
e4a8357715 Fix parameter types to pass arguments to scripting engine
Since `ArrayList` is highly compatible with COM, you can use it to pass an array to `ScriptControl`.
2024-08-25 12:56:01 +09:00
3a890168df Update ServiceMain.cs
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-24 22:27:26 +09:00
02681a135e Update the screen time feature 2024-08-24 22:24:26 +09:00
b345d655f1 Change the class names 2024-08-24 21:32:44 +09:00
7f6e21c96e
Update ScreenMatching.cs
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-24 16:18:24 +09:00
32975494f3
Update ScreenMatching.cs 2024-08-24 16:16:07 +09:00
ad06da549f
Update ScreenMatching.cs 2024-08-24 16:13:06 +09:00
ba9088f43f
Update ScreenMatching.cs 2024-08-24 15:57:42 +09:00
016239b014
Update ScreenMatching.cs 2024-08-24 15:40:15 +09:00
66d4926bba Update the screen time feature 2024-08-24 14:57:01 +09:00
7b62e47fd2 Update settings.example.ini 2024-08-24 14:14:01 +09:00
96b91b2298 Update the screen time feature 2024-08-24 13:44:48 +09:00
61ee6aeae0 Add thanks to Hacker News
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-08-23 13:11:32 +09:00
bbefd3331a Update .appveyor.yml 2024-08-23 12:21:37 +09:00
01477b97c5 Update .appveyor.yml 2024-08-23 12:17:35 +09:00
1751f81cce Update .appveyor.yml 2024-08-23 12:06:37 +09:00
cab0211e09 Update .appveyor.yml 2024-08-23 12:00:39 +09:00
2d5b79ceb1 Update .appveyor.yml 2024-08-23 12:00:31 +09:00
6b915a5b4c Update .appveyor.yml 2024-08-23 11:54:35 +09:00
1f0cb81105 Update .appveyor.yml 2024-08-23 11:48:13 +09:00
dbb008772e Update .appveyor.yml 2024-08-23 11:46:03 +09:00
0fa8286d08 Update .appveyor.yml 2024-08-23 11:44:37 +09:00
5146957ea1 Update .appveyor.yml 2024-08-23 11:42:46 +09:00
b183e1925d Update .appveyor.yml 2024-08-23 11:33:17 +09:00
158809732c Update README.md
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-23 08:56:01 +09:00
7633675b33 Update README.md 2024-08-23 08:54:01 +09:00
f8e6340fda Update README.md 2024-08-23 08:46:33 +09:00
4a02689c71 Update README.md 2024-08-23 08:44:42 +09:00
7899efcb9e Update README.md 2024-08-23 08:29:40 +09:00
2c67b77156 Update README.md 2024-08-23 08:28:12 +09:00
dc7b5a9fb2 Update MessageReceiver.cs
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-22 17:00:53 +09:00
97a930ccb3 Update MessageReceiver.cs 2024-08-22 16:59:58 +09:00
6ec6c07ad7 Update MessageReceiver.cs 2024-08-22 16:59:47 +09:00
3c90c76796 Update .appveyor.yml 2024-08-22 11:14:12 +09:00
0b0ca9912d Update .appveyor.yml 2024-08-22 10:39:01 +09:00
fabcdf185a Update .appveyor.yml 2024-08-22 10:34:14 +09:00
ad6eeb46d5 Update .appveyor.yml 2024-08-22 10:32:15 +09:00
6d43cb47a7 Update .appveyor.yml 2024-08-22 10:30:53 +09:00
ca9f0ba456 Update .appveyor.yml 2024-08-22 10:26:11 +09:00
bc0d6646e4 Update MainForm.cs
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-22 09:54:58 +09:00
8c59024b96 Update README.md 2024-08-22 04:16:36 +09:00
ecdc0767b8 Remove DeviceId package (not working) 2024-08-22 04:12:31 +09:00
f61dc98fa6 Update WelsonJS.Toolkit.sln 2024-08-22 04:11:06 +09:00
c985f1fa0a Update WelsonJS.Launcher build configurations 2024-08-22 04:08:37 +09:00
ce88ae603b Update WelsonJS.Launcher 2024-08-22 04:02:31 +09:00
1e82f18bc9 Update MainForm.cs 2024-08-22 03:58:35 +09:00
d8558a4398 Add WelsonJS.Launcher component 2024-08-22 03:36:58 +09:00
7c77daabfa Update .gitignore
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-22 00:55:54 +09:00
81a31c7b1f
Update http.js 2024-08-21 23:38:48 +09:00
f3f2cc482c
Update SECURITY.MD
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-21 08:03:52 +09:00
e8bc5348a8
Update README.md 2024-08-21 08:01:31 +09:00
fe31fd2c97 Update MessageReceiver.cs
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-20 19:37:10 +09:00
f6bbc31551 Update MessageReceiver.cs
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-20 16:31:23 +09:00
8821eb0ae0 fix 2024-08-20 16:03:27 +09:00
c497c0fb26 Update MessageReceiver.cs 2024-08-20 13:44:47 +09:00
ed9e1a6d05 fix 2024-08-20 13:42:44 +09:00
1fa024546a Add flag disabledMessageReceiver 2024-08-20 10:36:59 +09:00
b3548bc35f Update .gitignore 2024-08-20 09:50:30 +09:00
5de04579b7 Update settings.example.ini 2024-08-20 09:49:58 +09:00
80b3e49cb8 Some update configurations 2024-08-20 09:49:03 +09:00
68d100458f Merge branch 'master' of https://github.com/gnh1201/welsonjs 2024-08-20 09:35:27 +09:00
3765d21648
Update SECURITY.MD 2024-08-20 09:34:48 +09:00
e7ed4794e2 Merge branch 'master' of https://github.com/gnh1201/welsonjs 2024-08-20 09:25:56 +09:00
f181bf2696 Update MessageReceiver.cs, app.js #132 2024-08-20 09:25:50 +09:00
1704575cfb
Update SECURITY.MD 2024-08-20 09:11:19 +09:00
905c85a99c
Update SECURITY.MD 2024-08-20 09:06:57 +09:00
c8b3ac5d99 Related works for #132
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-19 17:04:50 +09:00
5d9fb71753 Replace GRPC proto file and delete the related file
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-19 00:35:23 +09:00
1863a76a4c Update build configurations
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-08-15 17:47:29 +09:00
8865723dd4 Update core-js version to 3.38.0
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-14 14:31:32 +09:00
eb05661e2b Update app.js 2024-08-14 14:25:55 +09:00
64e556f37a Update std.js
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-14 14:05:02 +09:00
a20ce41f73 Revert "Update std.js"
This reverts commit 9a583d0284.
2024-08-14 14:04:32 +09:00
9a583d0284 Update std.js 2024-08-14 14:04:17 +09:00
5ec537e142 Update std.js 2024-08-14 14:00:02 +09:00
243db3edaa Revert "Change variable naming convention, Remove dupilicate code (std.js)"
This reverts commit 3aa5a140d1.
2024-08-14 13:50:35 +09:00
3723f775bd Update .appveyor.yml
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-13 18:00:31 +09:00
83ecd79ec0 Update .appveyor.yml 2024-08-13 17:59:50 +09:00
9c77777577 Update .appveyor.yml 2024-08-13 17:59:18 +09:00
832bb12829 Revert "Add the package Costura.Fody"
This reverts commit d6012d88dd.
2024-08-13 17:39:26 +09:00
d6012d88dd Add the package Costura.Fody 2024-08-13 17:21:09 +09:00
d01d28fbf3
Update defaultService.js 2024-08-13 17:05:48 +09:00
f44f0b38b2 Update the files related to settings.ini
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-13 13:39:01 +09:00
d04e03200b some fixes 2024-08-13 11:21:48 +09:00
92bcb33171 Add settings.ini 2024-08-13 11:16:27 +09:00
41e542dc7a
Update FUNDING.yml
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-12 21:17:55 +09:00
c4740f7d61 Add ElasticsearchClient.cs, Update FileEventMonitor.cs 2024-08-12 21:15:03 +09:00
e8c69d1489 Update ScreenMatching.cs 2024-08-12 21:06:02 +09:00
5062d774b7 Some fixes 2024-08-12 21:05:17 +09:00
7de923f90c Remove the elasticsearch client library 2024-08-12 20:19:15 +09:00
7b03d9f020 Update .appveyor.yml 2024-08-12 17:16:16 +09:00
4ff438655d Update WelsonJS.Service.csproj 2024-08-12 17:10:34 +09:00
4ece37fdf4 Update FileEventMonitor 2024-08-12 17:08:32 +09:00
15bd7d40db Update ScreenMatching.cs, ServiceMain.cs 2024-08-12 16:53:31 +09:00
cf34039f5a Update FileEventMonitor.cs 2024-08-12 16:44:25 +09:00
f0a7316eef Some works #131 2024-08-12 16:42:37 +09:00
ee454527af Update FileEventMonitor.cs 2024-08-12 13:36:27 +09:00
5af61c3e76 Update ServiceMain.cs 2024-08-12 13:18:55 +09:00
e8ba073de2 Update FileEventMonitor.cs 2024-08-12 13:15:23 +09:00
0c03995f43 Update .appveyor.yml 2024-08-12 13:13:38 +09:00
5f0df92442 Update .appveyor.yml 2024-08-12 13:12:50 +09:00
1e16ff9483 Update pe.yar
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-12 13:07:16 +09:00
7c8fd0cd45 Update .appveyor.yml 2024-08-12 13:03:52 +09:00
bb2db7b64a Update .appveyor.yml 2024-08-12 13:02:11 +09:00
2631a8f577 some fixes 2024-08-12 13:00:04 +09:00
58d1829c9c Add Yara File Rule Matcher #131 2024-08-12 12:47:19 +09:00
1a4931e283
fix #122
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-08-08 11:07:52 +09:00
b2433e9057 Update .gitignore
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-07 16:31:19 +09:00
1b214a1604 Update bootstrap.bat 2024-08-07 11:58:00 +09:00
b8d2e362bf Update std.js 2024-08-07 11:55:50 +09:00
9f4f240493 Update std.js 2024-08-07 11:55:09 +09:00
3aa5a140d1 Change variable naming convention, Remove dupilicate code (std.js) 2024-08-07 11:52:34 +09:00
00868b708b
Update std.js 2024-08-06 22:03:24 +09:00
eead1f8775
Update std.js 2024-08-06 21:49:10 +09:00
cfadf1e369
Update std.js 2024-08-06 21:37:00 +09:00
fe31aa36bd
Update std.js 2024-08-06 21:34:50 +09:00
d6cf95b345
Update std.js 2024-08-06 21:34:01 +09:00
3ff02c442e
Update std.js 2024-08-06 21:30:31 +09:00
ca6f13196d
Update std.js 2024-08-06 21:15:59 +09:00
69888245bf
Update std.js 2024-08-06 21:00:02 +09:00
4a2fd7943a
Update std.js 2024-08-06 20:59:29 +09:00
3e86686613 Update .appveyor.yml 2024-08-06 20:27:40 +09:00
2bd104fc2f Update .appveyor.yml 2024-08-06 20:23:58 +09:00
334ec48d3e Update .appveyor.yml 2024-08-06 20:14:57 +09:00
ba5d038441 Update .appveyor.yml 2024-08-06 20:13:10 +09:00
93aababfc4 Update .appveyor.yml 2024-08-06 20:12:19 +09:00
daccf5e6de Create .appveyor.yml
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-06 20:08:17 +09:00
a6dbf1bb4b Update WelsonJS.Toolkit.csproj 2024-08-06 19:56:09 +09:00
34a9a843a4 JMT 2024-08-06 19:45:25 +09:00
8e88761547 Delete build_native_libraries.bat 2024-08-06 17:08:27 +09:00
1bb01be01d Remove the checked-in binaries #130 2024-08-06 17:05:51 +09:00
dbae10a4e5
Update har.js
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-08-03 21:56:26 +09:00
256ca14284
Update har.js
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-03 17:49:22 +09:00
ac2e1117a7
Update har.js 2024-08-03 17:10:34 +09:00
1b8fbf78bf
Update har.js 2024-08-03 16:49:30 +09:00
92e611f49a
Update har.js 2024-08-03 16:45:07 +09:00
5ff6680cee
Update har.js 2024-08-03 16:41:36 +09:00
aeef44d3d9
Update har.js 2024-08-03 15:53:30 +09:00
2e8c530ba9
Update har.js 2024-08-03 15:51:47 +09:00
c6cbe96e03
Update and rename hartool.js to har.js 2024-08-03 15:26:52 +09:00
45a1938aea
Create hartool.js 2024-08-03 15:25:41 +09:00
f55b70585a
Update SECURITY.MD 2024-08-03 14:07:30 +09:00
ff943d3fc2
Update SECURITY.MD
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-08-02 21:15:38 +09:00
a5672a16ff Update ScreenMatching.cs
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-08-02 16:53:33 +09:00
8df6270287 Update the screen time feature on WelsonJS.Service 2024-08-02 16:51:49 +09:00
70bce6eb72 Update .gitignore 2024-08-02 11:12:03 +09:00
75e386d2a7 Update .gitignore 2024-08-02 11:11:27 +09:00
05c06bffd2 Update WelsonJS.Service binaries 2024-08-02 11:09:32 +09:00
a7bc9fa21a Update ServiceMain.cs 2024-08-02 11:07:41 +09:00
8bd2382973 Update ServiceMain.cs 2024-08-02 11:07:04 +09:00
faf3d55d8d
Update README.md
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-07-31 18:17:09 +09:00
59d9d313f8
Update README.md 2024-07-31 18:14:57 +09:00
83e403cc54 Update setup.iss
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-07-31 16:19:08 +09:00
a80fd75ec3
Update SECURITY.MD 2024-07-31 09:44:30 +09:00
fc1694198b
Update SECURITY.MD 2024-07-31 09:41:12 +09:00
9ae992dc89 bug fix #126
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-07-31 00:43:42 +09:00
6297f9689d Add startInteractiveService.bat, uninstallService.bat 2024-07-30 18:17:26 +09:00
172a5109e9 Update setup.iss
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-07-30 15:46:11 +09:00
e881ec98ec Update README.md 2024-07-30 15:43:17 +09:00
6c9f905c2b Update README.md 2024-07-30 15:42:32 +09:00
0105ef9010 Update README.md 2024-07-30 15:41:05 +09:00
fe568f032e Add screenshot no.5 2024-07-30 15:40:17 +09:00
2766b2dcfc Update cover.png 2024-07-30 15:12:38 +09:00
2e37432990 Update README.md 2024-07-30 13:41:50 +09:00
38ad7ab669 Update README.md 2024-07-30 13:39:28 +09:00
27edbe4652 Update README.md 2024-07-30 13:30:10 +09:00
11abc2d1b3 Update README.md 2024-07-30 13:28:56 +09:00
119ad684ed Update README.md 2024-07-30 13:28:29 +09:00
accdf058c6 Update README.md 2024-07-30 13:22:05 +09:00
8d865b572d Change the cover image 2024-07-30 12:53:27 +09:00
3762dac556 Change the cover image 2024-07-30 12:53:06 +09:00
8f35bfb03b Update WelsonJS.Service
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-07-29 22:42:35 +09:00
3b09a47fb8 Update the Screen Matching feature 2024-07-29 22:28:07 +09:00
b687cf7727 Add Screen Matching feature 2024-07-29 21:43:14 +09:00
d5f55e0f28 Fix issue the cannot find the working directroy
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-07-29 16:06:04 +09:00
95a7588726 Revert "Some works for #124"
This reverts commit b5af648512.
2024-07-29 15:41:10 +09:00
f72db8bf2e Revert "Some works for #124"
This reverts commit f73b180329.
2024-07-29 15:41:05 +09:00
02d45ede0f Revert "Update defaultService.js"
This reverts commit ffd6cde177.
2024-07-29 15:40:11 +09:00
ffd6cde177 Update defaultService.js 2024-07-29 15:07:53 +09:00
f73b180329 Some works for #124 2024-07-29 15:04:22 +09:00
b5af648512 Some works for #124
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-07-29 01:35:46 +09:00
66879f229a Update installService.bat
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-07-27 21:38:38 +09:00
dad5c06a1b Add the service install script 2024-07-27 21:30:07 +09:00
0c5abb4658
Merge pull request #125 from gnh1201/dependabot/npm_and_yarn/requirejs-2.3.7
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Bump requirejs from 2.3.6 to 2.3.7
2024-07-26 17:29:31 +09:00
dependabot[bot]
0c09c5bd3b
Bump requirejs from 2.3.6 to 2.3.7
Bumps [requirejs](https://github.com/jrburke/r.js) from 2.3.6 to 2.3.7.
- [Commits](https://github.com/jrburke/r.js/compare/2.3.6...2.3.7)

---
updated-dependencies:
- dependency-name: requirejs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-26 08:25:56 +00:00
4a33238d7e Change the target framework version to 4.8, and renaming some functions 2024-07-26 17:24:56 +09:00
3b18896564 Fix incorrect version info of WelsonJS.Service
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-07-23 13:28:16 +09:00
84e094fc19 Update WelsonJS.Service binaries 2024-07-23 13:16:25 +09:00
639dfeeb68 Merge branch 'master' of https://github.com/gnh1201/welsonjs 2024-07-23 13:13:38 +09:00
f60f99fc73 Update WelsonJS.Service and related files 2024-07-23 13:13:33 +09:00
95572825c3
Update README.md
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-07-23 12:41:57 +09:00
7ef118955d Update WelsonJS.Toolkit binaries 2024-07-23 05:29:46 +09:00
c3114ab3f9 Add Microsoft Teams links to WelsonJS.Toolkit 2024-07-23 05:24:39 +09:00
e25baeae9c Delete sfx_config.txt 2024-07-23 05:09:56 +09:00
4afc6deab8 Create sfx_config.txt
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-07-23 04:29:50 +09:00
d15f23a3c1 Update app.js and clean up files 2024-07-23 04:26:38 +09:00
aa4ca1b212 Update WelsonJS.Service binaries 2024-07-23 01:17:31 +09:00
d0fe3d6acb Update ServiceMain.Designer.cs 2024-07-23 01:14:59 +09:00
be16fbfd72 Add screenshot 4 2024-07-23 01:07:21 +09:00
8c247adede Update WelsonJS.Service binaries and example 2024-07-23 00:37:12 +09:00
def32aa559 Update ServiceMain.cs 2024-07-23 00:23:01 +09:00
1e9533a9a5 Update app.js 2024-07-23 00:22:01 +09:00
debc806516 Update ServiceMain.cs 2024-07-23 00:20:20 +09:00
91631c6c1d Update ServiceMain.cs 2024-07-22 21:02:07 +09:00
360d37cd36 Update ServiceMain.cs
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-07-22 20:36:34 +09:00
d758957d68 Update ServiceMain.cs 2024-07-22 20:21:54 +09:00
7456bf903e Update WelsonJS.Service component 2024-07-22 20:15:31 +09:00
239b039e2a Update WelsonJS.Service component 2024-07-22 18:47:08 +09:00
7c6c633362 Update app.js 2024-07-22 16:12:45 +09:00
575e0cf6fc Add WelsonJS.Service component 2024-07-22 16:04:40 +09:00
31fb594904
Update app.js
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-07-22 00:56:55 +09:00
a592cd08cf
Update app.js 2024-07-22 00:09:57 +09:00
ebb254061d
Update app.js 2024-07-22 00:08:00 +09:00
f2239e75a9
Update http.js
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-07-21 19:55:42 +09:00
0764d2793d
Update app.js 2024-07-21 19:38:25 +09:00
4db58b0a3a
Update app.js 2024-07-21 19:23:38 +09:00
ca2976f314
Update app.js 2024-07-21 19:04:39 +09:00
688d4963a5
Update app.js 2024-07-21 19:03:52 +09:00
84dc76800b
Update app.js 2024-07-21 19:00:09 +09:00
190a5c81e3
Update app.js 2024-07-21 18:57:57 +09:00
b096dbe7c6
Update app.js 2024-07-21 18:37:54 +09:00
8b5abfe022
Update http.js fix #122
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-07-20 17:19:50 +09:00
4db44324e4
Update README.MD 2024-07-20 16:38:02 +09:00
1d21145d95
Update README.MD 2024-07-20 16:37:25 +09:00
ac7169cfe3
Update README.MD 2024-07-20 16:36:42 +09:00
ca3baeebdd
Update README.MD 2024-07-20 16:36:16 +09:00
b92f68e697
Update README.MD 2024-07-20 16:35:41 +09:00
a6b77826d5
Update README.MD 2024-07-20 16:35:22 +09:00
ce591bd9a7
Update README.MD 2024-07-20 16:34:50 +09:00
d71ce372a3
Update README.MD 2024-07-20 16:33:52 +09:00
89a2cd3684
Update SECURITY.MD 2024-07-20 15:04:57 +09:00
f6f4bd673d
Update machine-uuid-mysql.js
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-07-15 00:37:24 +09:00
2064d40bc9
Update machine-uuid-mysql.js 2024-07-15 00:36:44 +09:00
ace15e3248
Create machine-uuid-mysql.js 2024-07-15 00:35:00 +09:00
a586b7c23f
Update README.md
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-07-13 16:20:08 +09:00
8cdcff4660
Update README.md
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-07-12 16:26:13 +09:00
a56d8eb11b
Update setup.iss
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-07-10 20:47:08 +09:00
0a35ade427
Update wmi.js 2024-07-10 20:42:46 +09:00
7a98e9c8bf
Merge pull request #120 from gnh1201/shell-prefix
Add `.setPrefix()` method to `lib/shell` and related files, and supports BITS / 명령행 접두어 및 BITS 지원
2024-07-10 20:06:59 +09:00
aa489da1dc fix 2024-07-10 20:05:45 +09:00
c49d2720f2 fix 2024-07-10 19:54:18 +09:00
0f8557b09f Update autoit.js 2024-07-10 19:47:24 +09:00
c9bc48ad88 fix 2024-07-10 19:46:30 +09:00
4c68780e87 Update shell.js 2024-07-10 19:39:45 +09:00
b3a4125253 Update http.js 2024-07-10 19:37:39 +09:00
1309e2ab8f fix 2024-07-10 19:26:58 +09:00
97f68c39bb
Create .sonarcloud.properties 2024-07-10 15:20:48 +09:00
3c375f6a7c
Update http.js 2024-07-10 13:03:59 +09:00
92c9ae3063
Update http.js 2024-07-10 12:59:28 +09:00
be6937156f
Update http.js 2024-07-10 12:56:18 +09:00
92fdc2ff57
Update http.js 2024-07-10 12:51:16 +09:00
98b49b80a1
Update http.js 2024-07-10 12:07:52 +09:00
840e3bfb4c
Update http.js 2024-07-10 12:05:47 +09:00
4716a3a39e
Update shell.js 2024-07-10 12:03:22 +09:00
f4b2a68121
Update shell.js 2024-07-10 12:01:05 +09:00
c773406464
Update shell.js 2024-07-10 12:00:55 +09:00
25536a9b07
Update powershell.js 2024-07-10 11:57:24 +09:00
870ad0e52e
Update powershell.js 2024-07-10 11:56:53 +09:00
dbe48f9624
Update http.js 2024-07-10 11:48:28 +09:00
fd18d9d150
Update adb.js 2024-07-10 11:37:58 +09:00
83bc9a4b58
Update shell.js
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-07-10 11:32:02 +09:00
4b02143a44
Update http.js 2024-07-10 11:31:27 +09:00
9dda6f1e09
Update shell.js 2024-07-10 11:27:02 +09:00
3e67209ae8
Merge pull request #118 from gnh1201/catproxy-nmap
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
NMAP support with Caterpillar Proxy
2024-07-04 15:25:40 +09:00
6cf7d3e223
Merge branch 'master' into catproxy-nmap 2024-07-04 15:24:52 +09:00
7453b1f1ad
Update catproxy.js 2024-07-04 14:58:29 +09:00
8a935345c5
Update catproxy.js 2024-07-04 14:58:14 +09:00
2e9143c220
Update nmap.js 2024-07-04 14:57:20 +09:00
5ba7476685
Update catproxy.js 2024-07-04 14:52:48 +09:00
cde58c21a4
Update catproxy.js 2024-07-04 14:30:12 +09:00
145e22de21
Update http.js
Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
2024-07-04 10:56:48 +09:00
a20e0004d2
Update testloader.js
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-07-01 01:46:54 +09:00
c0e2b7731a
Update catproxy.js 2024-07-01 01:29:24 +09:00
2f974727d6
Update jsonrpc2.js 2024-07-01 01:27:51 +09:00
c91e01e13d
Update and rename caterpillar.js to catproxy.js 2024-07-01 00:53:58 +09:00
137793cd77
Update caterpillar.js
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-06-26 17:18:36 +09:00
27636a4a72
Update jsonrpc2.js 2024-06-26 17:17:15 +09:00
d86c9728e3
Update caterpillar.js 2024-06-26 17:16:35 +09:00
7de4e4f1be
Create caterpillar.js 2024-06-26 17:07:52 +09:00
3733eaea45
Update jsonrpc2.js 2024-06-26 16:37:04 +09:00
c9c70d9be6
Update README.md
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-06-21 14:31:11 +09:00
54d421fb4f Update pipe-ipc.js
Some checks failed
CodeQL / Analyze (csharp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2024-06-10 07:14:37 +09:00
14e87fbe63 Update lib/pipe-ipc, lib/xml 2024-06-10 07:13:45 +09:00
46eb8e6609 Clean up code 2024-06-10 06:23:35 +09:00
aa8f10b6a7 Update msoffice.js 2024-06-02 02:14:23 +09:00
b391867f14 fix mistypos 2024-06-02 02:04:46 +09:00
5f5386765d Add and fix the test files 2024-06-02 02:00:17 +09:00
b193fadd72 Update lib/msoffice, Create lib/filetypes.js and data 2024-06-01 06:58:11 +09:00
b6bff48cd0
Update README.md 2024-05-30 12:49:42 +09:00
1fd9adc8be
Update CITATION.cff 2024-05-30 12:08:59 +09:00
b74d64b7ad
Create CITATION.cff 2024-05-29 18:29:28 +09:00
02764be097
Add DOI 2024-05-29 17:22:24 +09:00
6af7be9572 Merge branch 'master' of https://github.com/gnh1201/welsonjs 2024-05-28 16:13:00 +09:00
ed182b42f9 Update screenshot3.png 2024-05-28 16:12:56 +09:00
87d2a41193
Update CONTRIBUTING.md 2024-05-27 17:59:55 +09:00
ff7322a5de
Add files via upload 2024-05-27 17:51:23 +09:00
66d2f0fb7e
Add files via upload 2024-05-27 17:49:50 +09:00
062d00098e
Update http.js 2024-05-22 18:36:01 +09:00
a96052ce27
Update http.js 2024-05-22 18:34:45 +09:00
0f07c61ad6
Update http.js 2024-05-22 18:30:07 +09:00
2157a23d9f
Update README.md 2024-05-22 13:44:38 +09:00
3286121461 Update setup.iss 2024-05-13 17:52:15 +09:00
6361cb333e Update setup.iss 2024-05-13 17:44:16 +09:00
30ab79eae3 Edit installer files 2024-05-13 17:37:54 +09:00
c9c6481b3f Update AssemblyInfo.cs 2024-05-13 17:09:24 +09:00
e3e68bf696 Add BitmapUtils.cs, Toolkit.cs and more 2024-05-13 17:05:24 +09:00
2edda2b710 Update BitmapUtils.cs 2024-05-13 16:54:17 +09:00
24dcfdb2cc Add BitmapUtils.cs and more 2024-05-13 16:53:33 +09:00
2408e89940
Update chrome.js 2024-04-24 03:42:47 +09:00
547da8ab60
Update chrome.js 2024-04-24 03:41:38 +09:00
c1cc02c217
Update chrome.js 2024-04-24 03:33:12 +09:00
0b4cacf417
Update chrome.js 2024-04-24 03:28:57 +09:00
9bab66ab53 Add VoC link 2024-04-07 20:28:21 +09:00
02073e2247 Update README.md 2024-04-07 16:02:06 +09:00
4aff088de0 Update README.md 2024-04-07 16:01:10 +09:00
475739e9e9 Update README.md 2024-04-07 15:58:21 +09:00
a5f36ea692 Update jsonrpc2.js 2024-04-07 15:55:16 +09:00
6537f9a635 Update jsonrpc2.js 2024-04-07 15:53:55 +09:00
e332682fd2 Add JSON-RPC 2.0 support 2024-04-07 15:48:40 +09:00
9f24bf6384 Update lib/adb.js and delete unnecessary files 2024-04-07 15:30:30 +09:00
b7ac95d8ea Fix #111 2024-04-06 20:46:41 +09:00
14145d6f70 fix indentation 2024-04-06 20:26:58 +09:00
db5c294ab9 Fix the feedback 2024-04-05 #109 2024-04-06 20:26:07 +09:00
6591ee7074 Add linq.js 4.0.2 2024-04-06 15:17:59 +09:00
3f07d2355d Update README.md 2024-04-02 13:58:09 +09:00
b1a7a63987
Merge pull request #108 from fossabot/add-license-scan-badge
Add license scan report and status
2024-04-02 13:50:30 +09:00
7e75b5a812 Add FOSSA report link 2024-04-02 13:39:27 +09:00
d8a8b7e27c remove fossa_report 2024-04-02 11:41:51 +09:00
2d67c88fc8 Add fossa_report 2024-04-01 18:29:00 +09:00
87a16c69b6
Update package.json 2024-04-01 18:14:11 +09:00
fossabot
937d540db5 Add license scan report and status
Signed off by: fossabot <badges@fossa.com>
2024-04-01 06:05:12 -03:00
61de14a449 Update README.md 2024-03-21 02:09:23 +09:00
7f37d5e396 Update README.md 2024-03-21 02:05:12 +09:00
c7869d6819 Update README.md 2024-03-21 01:53:18 +09:00
ab6b28f220 Update README.md 2024-03-21 01:44:47 +09:00
7cc1dfd06a Update README.md 2024-03-21 01:37:38 +09:00
d4191917f6 Update README.md 2024-03-21 01:05:15 +09:00
c41bc5b791 Update README.md 2024-03-21 01:25:08 +09:00
853eabc898 Update README.md 2024-03-21 01:23:45 +09:00
8aa0005427 Update README.md 2024-03-21 01:22:09 +09:00
0b9c5f0c5e Fix summernote issues 2024-03-20 21:12:59 +09:00
0e324a349d Fix summernote issues 2024-03-20 16:30:30 +09:00
f7b4934f6b Update README.md 2024-03-20 11:22:37 +09:00
533521239f Add method Browser.waitUntil 2024-03-20 11:13:58 +09:00
05df3518ac Update encryptor.js 2024-03-19 18:00:08 +09:00
e0df993bad Update encryptor.js 2024-03-19 17:59:34 +09:00
4c88348ddf Update README.md 2024-03-19 17:48:40 +09:00
1308d7a115 Update README.md 2024-03-19 17:45:23 +09:00
aca13b53eb Update README.md 2024-03-19 17:44:39 +09:00
f105bb2eb7 Update README.md 2024-03-19 17:39:22 +09:00
40972575b6 Update README.md 2024-03-19 17:25:42 +09:00
98fe04291b Update README.md 2024-03-19 17:24:00 +09:00
ddb9a47f59 Update README.md 2024-03-19 17:23:01 +09:00
36c5a8a586 fix description 2024-03-19 17:21:51 +09:00
c8b5e82b12 Fix descriptions 2024-03-19 17:17:15 +09:00
2fb4b62b8d Update testloader.js, test-misc.json 2024-03-12 15:07:12 +09:00
51ef1508bd
Update FUNDING.yml 2024-02-23 17:10:22 +09:00
85fd0e2e01 Update encryptor.js 2024-01-30 18:28:54 +09:00
94f11d73cd Update app.js 2024-01-27 14:12:40 +09:00
302b33d48b Update sendmail.js 2024-01-27 14:01:57 +09:00
9cdfd205bf Remove the package: html5media 2024-01-27 13:51:32 +09:00
64d178a53a
Update README.MD 2024-01-27 10:02:42 +09:00
a5ba2423d5
Update README.MD 2024-01-27 10:02:19 +09:00
bbd45ab9f9
Update README.MD 2024-01-27 01:17:12 +09:00
ef755b3217
Update README.MD 2024-01-27 01:16:49 +09:00
4bd770d078 Update app.js 2024-01-27 00:50:25 +09:00
4db4d98f0b HIGHT(ISO/IEC 18033-3) encryption and decryption 2024-01-27 00:50:07 +09:00
453e63da2e Update app.js 2024-01-26 18:27:11 +09:00
01be6b6252 Update app.js 2024-01-26 16:58:27 +09:00
bafc0a085d Update app.js 2024-01-26 16:57:53 +09:00
79c64726e2 Update app.js 2024-01-26 16:55:49 +09:00
7d01adb54b Update HIGHT.cs 2024-01-26 16:29:22 +09:00
436ce3d88d
Update SECURITY.MD 2024-01-25 11:08:03 +09:00
d0593958e7
Update SECURITY.MD 2024-01-25 10:54:55 +09:00
0a069e3f3a
Update README.md 2024-01-25 06:14:01 +09:00
83d90a8110
Update FUNDING.yml 2024-01-25 06:12:30 +09:00
a268b5acc6
Update FUNDING.yml 2024-01-25 06:11:56 +09:00
bcdf4f9165
Update README.md 2024-01-25 06:10:54 +09:00
8f733eba64
Update README.md 2024-01-25 05:57:02 +09:00
8515627f82 Merge branch 'master' of https://github.com/gnh1201/welsonjs 2024-01-25 01:33:03 +09:00
f4b86735fb Add EncryptStringHIGHT(), DecryptStringHIGHT() 2024-01-25 01:32:59 +09:00
166dd70ef9
[lib/http] cURL error with non-escaped ampersand on Command Prompt #103 2024-01-24 19:23:39 +09:00
541078bda8 Add WelsonJS.Cryptography.HIGHT 2024-01-24 13:28:20 +09:00
cfc9501554 Update app.js, lib/std.js 2024-01-08 15:42:54 +09:00
04c2325ade
Update chrome.js 2024-01-08 01:41:35 +09:00
6a0491c419
Update README.MD 2024-01-05 21:41:14 +09:00
60854fc9df
Update README.MD 2024-01-05 21:36:39 +09:00
df8b345ddf Update README.md 2024-01-05 16:17:09 +09:00
e650915bb9 Update README.md 2024-01-05 16:11:30 +09:00
ed2f98e558 Update README.md 2024-01-05 16:05:43 +09:00
1f7a4a0778 Update README.md 2024-01-05 16:01:58 +09:00
c179b2e478 Add image 2024-01-05 16:01:15 +09:00
c0c64de20d Update NamedSharedMemory.cs 2024-01-04 18:07:04 +09:00
82deec7a81 Remove the experimental files 2024-01-04 17:51:16 +09:00
1972c4f44a experimental 2024-01-04 17:43:57 +09:00
43a56c5360 experimental 2024-01-04 17:40:41 +09:00
604fc27a59 experimental 2024-01-04 17:35:59 +09:00
f0504e12ec Update testloader.js 2024-01-04 16:14:13 +09:00
7f9840f765 Merge branch 'master' of https://github.com/gnh1201/welsonjs 2024-01-04 15:55:41 +09:00
b1a0e91dd9 Update the native component 2024-01-04 15:55:21 +09:00
097f146499 Update test-misc.json 2024-01-04 15:48:09 +09:00
11209fa8d7 Update test-misc.json 2024-01-04 15:47:57 +09:00
bd5bf9ebe0 Update testoader.js 2024-01-04 15:47:05 +09:00
28fd89f22d shared memory #96 2024-01-04 15:23:26 +09:00
dddfa3cc47 Update testloader.js #96 2024-01-04 12:05:47 +09:00
5ffdea15de fix typo 2023-12-29 15:23:24 +09:00
6fe9d097a8 shared memory 2023-12-29 15:22:20 +09:00
29a40ab83d shared memory 2023-12-29 15:09:31 +09:00
fcd53969f1 shared memory 2023-12-29 15:03:02 +09:00
1bd57f6fef Add WelsonJS.Toolkit.Experimental.dll 2023-12-28 16:11:21 +09:00
7c06504281 Add WelsonJS-WebRequest powershell script 2023-12-28 13:44:00 +09:00
c9dbcc24e3
Update README.md 2023-12-28 13:20:11 +09:00
83abad910a Add screenshot 3 2023-12-28 13:16:51 +09:00
65abb93ee5
Update README.md 2023-12-28 13:02:40 +09:00
924e581fbb
Add files via upload 2023-12-28 13:02:13 +09:00
44573236f7 Update app.js 2023-12-28 11:48:39 +09:00
0d5660726d Update app.js 2023-12-28 11:48:27 +09:00
2775e277fd Update app.js 2023-12-28 11:46:33 +09:00
9c1250ac22
Update chrome.js 2023-12-27 03:51:35 +09:00
80dfe4c915 Update chrome.js 2023-12-27 03:31:54 +09:00
285e90494d
Update preconfigure.bat 2023-12-27 02:11:29 +09:00
3e19d03cd1 IEMaxScriptStatements.bat and registerDLLs.bat is merged to preconfigure.bat 2023-12-27 02:10:12 +09:00
04e7dc82af Update chrome.js 2023-12-27 01:33:43 +09:00
e8e617658c Remove unused libraries, Fix the rendering-related resources 2023-12-23 05:13:25 +09:00
df3ee0331c Update WelsonJS.Toolkit.csproj 2023-12-23 01:55:35 +09:00
d3ae29ffdd Update README.MD 2023-12-22 18:15:50 +09:00
5d1a539e9b
Update README.MD 2023-12-22 18:11:50 +09:00
30f60fd304
Update README.MD 2023-12-22 18:11:03 +09:00
ca8a0af14e Update README.MD 2023-12-22 18:03:01 +09:00
e0b915faec Update README.MD 2023-12-22 17:59:37 +09:00
5aa9eb1392 Update README.MD 2023-12-22 17:58:26 +09:00
320063ad1d Update README.MD 2023-12-22 17:54:58 +09:00
ec70b2e648 Update README.MD 2023-12-22 17:54:03 +09:00
084535597d Update README.MD 2023-12-22 17:52:27 +09:00
5ef2cd92bf Update README.MD 2023-12-22 17:50:50 +09:00
573d8c76d3 Update the additional binaries information 2023-12-22 17:49:07 +09:00
e7068f0f97 Add LZ77 (MsCompress) algorithm implementation 2023-12-22 16:00:08 +09:00
3cfc3fccf5 Update lib/toolkit.js 2023-12-20 17:58:42 +09:00
0d3052e659 Update lib/std.js, lib/toolkit.js 2023-12-20 17:01:24 +09:00
31b28f2945 Update testloader.js 2023-12-19 07:20:33 +09:00
f6d756f92b msoffice #93 2023-12-19 06:47:48 +09:00
92dedd182e Update officeloader.js 2023-12-19 05:56:16 +09:00
5f487d9409 Update lib/msoffice, officeloader #93 2023-12-19 05:12:05 +09:00
94a0b66c12
Update SECURITY.MD 2023-12-18 15:11:13 +09:00
28edbcc135
Update SECURITY.MD 2023-12-18 15:10:35 +09:00
f1982dd69e
Update SECURITY.MD 2023-12-18 15:01:45 +09:00
08e87edb71 Update native component 2023-12-17 00:12:19 +09:00
ba47a7f62d Update native component 2023-12-17 00:11:42 +09:00
9bc4621962 Updated native component source code 2023-12-16 23:42:17 +09:00
e74afcf112 Merge branch 'master' of https://github.com/gnh1201/welsonjs 2023-12-14 04:47:51 +09:00
44fa579390 [Toolkit] Access to a shared memory #96 2023-12-14 04:47:47 +09:00
c7682acbd2
Update SECURITY.MD 2023-12-14 03:26:58 +09:00
821629eb5a
Update SECURITY.MD 2023-12-14 03:25:28 +09:00
32020e0d84
Update msoffice.js 2023-12-11 18:18:47 +09:00
35eb144ce8
Update msoffice.js (compatibility) 2023-12-11 18:18:25 +09:00
a000958f99
Update msoffice.js 2023-12-11 18:10:15 +09:00
3fbb73e3e1
Update msoffice.js 2023-12-11 18:09:53 +09:00
00f92f0eb9
Update msoffice.js 2023-12-11 17:58:31 +09:00
bf796ed61c
Update msoffice.js 2023-12-11 17:56:31 +09:00
2b524dcb13
Update msoffice.js 2023-12-11 17:53:40 +09:00
79bc3fe593 Update lib/system.js and related files 2023-12-11 16:54:21 +09:00
c4dfca7c62 Update app.js, helloworld.js 2023-12-11 16:10:55 +09:00
ecbef69860
Update app.js 2023-12-11 15:35:33 +09:00
fffd5eb872
Update FUNDING.yml 2023-12-11 14:38:05 +09:00
0283ad1bc2
Update app.js 2023-12-11 14:22:00 +09:00
871fe130af Update app.js 2023-12-11 12:42:33 +09:00
0266da168f
Update app.js 2023-12-11 12:10:54 +09:00
7659507e9e
Update app.js 2023-12-11 11:40:31 +09:00
4e3b7f7aee
Update app.js 2023-12-11 11:20:36 +09:00
0eebb269f0
Update README.md 2023-12-04 19:01:58 +09:00
2596bef850
Update README.md 2023-12-04 18:59:22 +09:00
e502256bed
Update binaries_meta.json 2023-12-01 22:35:30 +09:00
99bdbc41ba
Update binaries_meta.json 2023-12-01 22:33:43 +09:00
4d19c93814
Update binaries_meta.json 2023-12-01 21:55:09 +09:00
7e30b4ab1a
Update and rename bin_profile.json to binaries_meta.json 2023-12-01 21:23:47 +09:00
349f3589ff
Update bin_profile.json 2023-12-01 16:25:59 +09:00
049d1ee294
Update bin_profile.json 2023-12-01 16:17:47 +09:00
a3dcc8fbd7
Update bin_profile.json 2023-12-01 16:14:03 +09:00
f87ecc0e45
Create bin_profile.json 2023-12-01 15:41:18 +09:00
1fda56bd7e Cleanup a legacy 2023-11-28 01:50:34 +09:00
5858dff783
Update README.MD 2023-11-28 01:45:24 +09:00
b87aad537a Change the calling convention excel.getCellByPosition() to excel.getCellByPosition(x, y).setValue() 2023-11-28 00:51:54 +09:00
44c6e22dc8 MS Office #93 2023-11-27 19:14:11 +09:00
ae04570d40 Support Microsoft Excel #93 + ChatGPT 2023-11-27 18:20:54 +09:00
796918e07e ChatGPT + MS Office 2023-11-27 18:03:22 +09:00
848bded217 msoffice.js 2023-11-27 17:04:01 +09:00
52888517ee lib/msoffice.js, officetest.js 2023-11-27 16:56:18 +09:00
4558db2d5e Create msoffice.js 2023-11-24 17:36:28 +09:00
aecd998301
Update README.md 2023-11-24 16:28:17 +09:00
4bf9cb4c5c Add WYSIWYG HTML Editor #92 2023-11-22 18:02:03 +09:00
95a6324e18
Update README.md 2023-11-14 17:51:01 +09:00
22c140dcbd
Update README.md 2023-11-14 17:49:05 +09:00
088e4c9010
Update README.md 2023-11-14 17:48:02 +09:00
9e6d39abb4
Update FUNDING.yml 2023-11-14 17:38:28 +09:00
fc3697217a
Update README.md 2023-11-10 10:29:08 +09:00
795d121422 fix typo 2023-11-07 11:37:05 +09:00
543f7b61e7 Remove gtk.demo.js, toolkit.demo.js, squel.demo.js, and merge to testloader.js 2023-11-07 11:24:36 +09:00
f8ee2cf3e5 Remove gtk.demo.js and merge to testloader.js 2023-11-07 11:04:21 +09:00
4fde95bbf6 Update testloader.js 2023-11-06 12:07:10 +09:00
4906799170 Fix Enumerator.toArray method and related issues 2023-11-06 11:23:09 +09:00
da36ad57be Update lib/http.js, testloader.js 2023-10-31 05:49:11 +09:00
0efc455cf9 Update testloader.js and more 2023-10-31 05:41:52 +09:00
f393a99dc5 Update 2023-10-31 03:13:02 +09:00
4ea98b1540 Update 2023-10-31 02:02:02 +09:00
934009a6c0 Update 2023-10-30 19:51:48 +09:00
141c7709b3 Update test-oss-20231030.json 2023-10-30 17:17:56 +09:00
ceb7de458e Update app/index.js, app/test.html, testloader.js 2023-10-30 17:14:31 +09:00
0f4dfcef20 Update app.hta, app/index.js, app/signin.html, app/test.html 2023-10-30 16:58:29 +09:00
c3e9d1b179 Add GUI Router 2023-10-30 16:11:51 +09:00
79fb080e9f Update testloader,js, and test profile 2023-10-30 14:36:22 +09:00
28474ad477 Update testloader.js 2023-10-30 14:01:37 +09:00
bfd826a0ea Change "utf-8" to FILE.CdoCharset.CdoUTF_8 2023-10-30 13:56:43 +09:00
feef8e9f73 Update lib/file.js, testloader..js 2023-10-30 13:41:43 +09:00
6e5e1b99e2 Create the test profile 2023-10-30 12:55:48 +09:00
9ff1f617b8
Fixed bug: broken GUI sample #86
Fixed bug: broken GUI sample #86, Reported by @eogloblin, in 2023-10-26
2023-10-26 18:59:01 +09:00
1a460afaa2
Update system.js 2023-10-24 11:13:19 +09:00
130d3d1569
Update pipe-ipc.js 2023-09-26 14:44:37 +09:00
5d3d2a06d7
Update http.js 2023-09-26 11:57:35 +09:00
0fbd38db9f
Update setup.iss 2023-09-26 11:57:13 +09:00
2e625a6392
Update package.json 2023-09-26 11:56:59 +09:00
ea5a70e03d
Update pipe-ipc.js 2023-09-26 11:24:12 +09:00
20ac966a61
Update pipe-ipc.js 2023-09-22 14:46:40 +09:00
c3435f7aac
Update pipe-ipc.js 2023-09-22 14:43:29 +09:00
c0dc768588
Update file.js 2023-09-21 21:45:26 +09:00
f904b43777
Update pipe-ipc.js 2023-09-21 21:44:26 +09:00
01b5e7d46f
Update shell.js 2023-09-21 21:13:24 +09:00
ae82ef5d95
Update file.js 2023-09-21 20:47:43 +09:00
9b0e67a12a
Update pipe-ipc.js 2023-09-21 20:46:56 +09:00
d4214f7f34
Update shell.js 2023-09-21 18:58:28 +09:00
6b55a2d0de
Update pipe-ipc.js 2023-09-21 18:57:42 +09:00
c4ccdaf1aa
Update file.js 2023-09-21 18:55:35 +09:00
2d72f6a87b
Update pipe-ipc.js 2023-09-21 16:58:30 +09:00
34668ad54e
Update pipe-ipc.js 2023-09-21 16:53:58 +09:00
88482f5ba8
Update file.js 2023-09-21 16:39:49 +09:00
2b27f369bd
Update shell.js 2023-09-21 15:08:52 +09:00
f22364b2f9
Update pipe-ipc.js 2023-09-21 15:08:03 +09:00
cbac701e7e
Update http.js 2023-09-21 15:07:22 +09:00
2912ca8b4b
Update http.js 2023-09-21 10:59:51 +09:00
7acb695877
Update shell.js 2023-09-21 10:59:22 +09:00
c9c6d87803
Update file.js 2023-09-20 19:07:50 +09:00
59e76de85d
Update pipe-ipc.js 2023-09-20 19:07:18 +09:00
44a9a32775
Merge pull request #82 from gnh1201/pipe-ipc-shell
Enhance the shell interface with PIPE IPC
2023-09-20 16:48:11 +09:00
3999bcc171
Update pipe-ipc.js 2023-09-20 14:59:30 +09:00
30f16cf3e8
Update shell.js 2023-09-20 14:35:21 +09:00
04ec2586a5
Update pipe-ipc.js 2023-09-20 14:32:27 +09:00
01cfdb0f72
Update shell.js 2023-09-20 12:27:38 +09:00
b60ef15c91
Update pipe-ipc.js 2023-09-20 12:25:52 +09:00
a035304803
Update pipe-ipc.js 2023-09-19 19:28:04 +09:00
d05d4deb03
Create ipctest.js 2023-09-19 16:37:14 +09:00
9080a177f1
Merge pull request #81 from gnh1201/pipe-ipc-file
Pipe ipc file
2023-09-19 16:32:10 +09:00
f40a45c5f1
Update pipe-ipc.js 2023-09-19 16:23:09 +09:00
e28f346447
Update file.js 2023-09-19 16:08:24 +09:00
7a1086108c
Update pipe-ipc.js 2023-09-19 16:07:39 +09:00
de20821b98
Update file.js 2023-09-19 15:55:45 +09:00
3baaf8dd2b
Update pipe-ipc.js 2023-09-19 15:54:31 +09:00
4a3d044f02
Update pipe-ipc.js 2023-09-18 23:25:18 +09:00
145be2a894
Update pipe-ipc.js 2023-09-18 21:06:23 +09:00
26fbacf695
Update system.js 2023-09-13 12:26:05 +09:00
6ff0f3cbd3
Update system.js 2023-09-13 12:24:29 +09:00
2572cd5876
Update setup.iss 2023-09-11 15:49:48 +09:00
d8c21ac9cc
Change GPLv2 to GPLv3 2023-09-09 01:33:02 +09:00
5a25d0046b
Update README.md 2023-09-07 20:43:45 +09:00
2467ee77d2
Add files via upload 2023-09-07 20:34:16 +09:00
0c211f4055
Add files via upload 2023-09-07 20:34:01 +09:00
bdcf7c8fe4
Add files via upload 2023-09-07 20:33:45 +09:00
b81eae42d7
Add files via upload 2023-09-07 20:33:19 +09:00
64d8850d03
Add files via upload 2023-09-07 20:14:22 +09:00
cdd086bb98
Add files via upload 2023-09-07 20:14:06 +09:00
8903a3ca8f
Update README.md 2023-09-06 18:25:49 +09:00
e4e53b0dd3
Update package.json 2023-09-05 15:42:36 +09:00
921555438c
Update FUNDING.yml 2023-09-05 11:37:14 +09:00
847303b6ae
Create FUNDING.yml 2023-09-05 11:36:20 +09:00
f2caf930d2
Update README.MD 2023-09-05 10:40:18 +09:00
b2165c9eff
Update README.MD 2023-09-05 10:20:37 +09:00
40774e5989
Create WelsonAppLoader.proto 2023-09-05 03:48:55 +09:00
1eaae35649
Update README.md 2023-09-05 03:46:34 +09:00
0539e508ef
Update SECURITY.MD 2023-09-05 03:44:28 +09:00
47718ecfe9
Update SECURITY.MD 2023-09-05 03:43:43 +09:00
3794bf3e18
Update README.MD 2023-09-05 03:40:20 +09:00
97b9076745
Update README.MD 2023-09-05 03:36:25 +09:00
a674a0f3b7
Add files via upload 2023-09-05 03:27:16 +09:00
01f0ae6254
Update app.js 2023-09-05 03:27:00 +09:00
db55b30106
Add files via upload 2023-09-05 03:26:16 +09:00
9c7ba07017
Add support gRPC (gRPC proto 3) 2023-09-05 03:24:42 +09:00
f83b39bc88
Update README.MD 2023-09-05 00:00:00 +09:00
2c4ee3a912
Add files via upload 2023-08-30 14:37:08 +09:00
a5ece6f187
Add files via upload 2023-08-30 14:33:09 +09:00
629da37bec
Update README.md 2023-08-08 14:37:48 +09:00
1ad2d1bac7
Update README.md 2023-08-08 14:37:07 +09:00
2049b14bda
Update README.md 2023-08-07 17:30:01 +09:00
68b7cae0d5
Update README.md 2023-08-04 22:58:32 +09:00
12995a3982
Update README.md 2023-08-04 22:57:49 +09:00
4374a210d9
Update README.md 2023-08-04 22:56:29 +09:00
e1d3d3187a
Update README.md 2023-08-04 22:54:08 +09:00
054715410d
Update README.md 2023-08-04 22:51:17 +09:00
e25444c6f0
Update README.md 2023-08-04 22:35:59 +09:00
959e17f673
Update README.md 2023-08-02 16:08:10 +09:00
008f0044e3 [app] Add support ReasonML/Rescript #77 2023-08-02 16:06:08 +09:00
424769d1d5 [app] Add support ReasonML/Rescript #77 2023-08-02 15:59:05 +09:00
e693de128f Remame the directory crypto-js to crypto-js-3.3.0 2023-07-27 18:12:22 +09:00
4272b5a199 Add libraries: CryptoJS 2023-07-27 18:11:24 +09:00
1a8d808a7b Add CryptoJS libraries 2023-07-27 18:09:20 +09:00
b894475d62
Update SECURITY.MD 2023-07-27 17:30:57 +09:00
f71e4c16e0
Update SECURITY.MD 2023-07-27 15:47:32 +09:00
905ad5b82f
Update SECURITY.MD 2023-07-27 15:46:27 +09:00
544cbd0bc6
Merge pull request #74 from welsonjs-ng/master
Update SECURITY.MD
2023-07-27 15:34:13 +09:00
164ef1d378
Update SECURITY.MD 2023-07-27 15:30:27 +09:00
97cfbd3835
Update SECURITY.MD 2023-07-27 15:29:59 +09:00
37ddae06d5
Merge pull request #1 from gnh1201/master
표기사항 변경 및 modern ie 관련 변경
2023-07-27 15:21:12 +09:00
6cc413a529
Update SECURITY.MD 2023-07-27 15:18:20 +09:00
4dda3c6d40
Update SECURITY.MD 2023-07-27 15:14:55 +09:00
c24a04711f
Update README.MD 2023-07-27 14:24:07 +09:00
14f3d56441
Update app.js 2023-07-27 01:38:32 +09:00
6da822fc80
Update README.md 2023-07-19 11:34:37 +09:00
325247bd75
Update README.md 2023-07-19 11:33:58 +09:00
f7998c3f15
Create LICENSE 2023-07-18 16:04:17 +09:00
562456c59e
Rename LICENSE to LICENSE_MSRL 2023-07-18 16:03:23 +09:00
57bed80d1c
Update SECURITY.MD 2023-07-02 02:22:19 +09:00
bb2151b999
Update SECURITY.MD 2023-06-29 19:43:08 +09:00
cef1d89f8d
Update virustotal.js 2023-06-21 16:52:03 +09:00
ae2f87962e
Update virustotal.js 2023-06-21 16:41:32 +09:00
c9b5cc7227
Create certchecker.js 2023-06-21 16:35:46 +09:00
c6c44cb981
Create virustotal.js 2023-06-21 16:33:51 +09:00
dffa775658
Update http.js 2023-04-14 18:16:09 +09:00
d1d91b74e3
Update SECURITY.MD 2023-03-14 17:17:49 +09:00
613f2d250f
Update SECURITY.MD 2023-03-14 17:15:45 +09:00
761148f350
Update SECURITY.MD 2023-03-14 17:14:07 +09:00
a0f2d645e5
Update std.js 2023-03-14 14:13:22 +09:00
388c0ae3d0
Update std.js 2023-03-14 13:50:26 +09:00
17bbdadbb4
Update std.js 2023-03-14 13:41:49 +09:00
6ab0343834
Update std.js 2023-03-10 17:47:18 +09:00
6abe48ba5a
Update std.js 2023-03-10 17:46:50 +09:00
401cb4296e
Update powershell.js 2023-03-10 11:43:35 +09:00
aed2ab6e04
Update powershell.js 2023-03-10 11:36:36 +09:00
f5833dd103
Update powershell.js 2023-03-10 11:28:23 +09:00
3008ea8813
Update powershell.js 2023-03-10 11:28:02 +09:00
8b1722cedb
Update powershell.js 2023-03-10 11:26:53 +09:00
4867faab16
Update powershell.js 2023-03-09 19:16:00 +09:00
42f971ab07
Update http.js 2023-03-09 11:42:55 +09:00
ba33419c67
Update http.js 2023-03-09 11:38:56 +09:00
e4d076bd47
Update chrome.js 2023-02-01 11:03:14 +09:00
27b324b3be
Update chrome.js 2023-02-01 11:02:55 +09:00
83e4c02f16
Update std.js 2023-02-01 10:50:15 +09:00
f79e1e0e65
Update README.md 2023-01-31 12:04:14 +09:00
c187fa43a0 Update strings.js 2023-01-31 11:51:38 +09:00
b3facdcaae
Update xml.js 2023-01-05 05:37:13 +09:00
0ab224b987
Update xml.js 2023-01-05 04:36:12 +09:00
a1c45e9bd5
Update bootstrap.js 2023-01-03 16:35:53 +09:00
30a332c1c4 Add support TypeScript 2022-12-22 16:17:10 +09:00
820d5dafc8
Update app.js 2022-12-22 16:01:41 +09:00
493 changed files with 146433 additions and 6363 deletions

47
.appveyor.yml Normal file
View File

@ -0,0 +1,47 @@
version: 0.2.7.build{build}
image: Visual Studio 2019
clone_folder: C:\projects\welsonjs
environment:
ORGANIZATION_ID: 8ee5ec82-36dc-4619-ac33-5bc1117428fe
PROJECT_SLUG: welsonjs
ARTIFACT_CONFIGURATION_SLUG: initial
matrix:
- CONFIGURATION: Debug
SIGNING_POLICY_SLUG: test-signing
- CONFIGURATION: Release
SIGNING_POLICY_SLUG: release-signing
before_build:
- nuget restore WelsonJS.Toolkit
build_script:
- msbuild "C:\projects\welsonjs\WelsonJS.Toolkit\WelsonJS.Toolkit.sln" /verbosity:minimal /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" /p:Configuration=%CONFIGURATION% /p:Platform="x86"
after_build:
- cmd: mkdir 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.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\*
artifacts:
- path: artifacts.zip
name: WelsonJS.Toolkit
deploy:
- provider: Webhook
url: https://app.signpath.io/API/v1/%ORGANIZATION_ID%/Integrations/AppVeyor?ProjectSlug=%PROJECT_SLUG%&SigningPolicySlug=%SIGNING_POLICY_SLUG%&ArtifactConfigurationSlug=%ARTIFACT_CONFIGURATION_SLUG%
authorization:
secure: nABfe+lksIRfS7lVnkq3EdIYNH8KOka+5ZFTUJqUW2nckBubhrlAXarbCPJHLp9FWWf3zxAWhNwT0It+qyqPRQ==
notifications:
- provider: Email
to:
- abuse@catswords.net
subject: 'Build #{{build}} {{status}}'
on_build_success: false
on_build_failure: true

2
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,2 @@
github: gnh1201
custom: ['https://gnh1201.link']

View File

@ -32,7 +32,7 @@ jobs:
strategy:
fail-fast: false
matrix:
language: [ 'csharp', 'javascript', 'python' ]
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://git.io/codeql-language-support
@ -42,7 +42,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# 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).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@ -67,4 +67,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v2

23
.github/workflows/llm-code-review.yml vendored Normal file
View File

@ -0,0 +1,23 @@
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 }}

15
.gitignore vendored
View File

@ -103,8 +103,13 @@ dist
# TernJS port file
.tern-port
# Custom directories and files
bin/
packages/
config.xml
staticip.xml
# user private assets
bin
data/*-apikey.txt
data/*.nomedia.txt
app/assets/img/_templates
app/assets/img/_captured
settings.ini
defaultService.js
lib/*.private.js
data/python313.zip

9
.gitmodules vendored Normal file
View File

@ -0,0 +1,9 @@
[submodule "app/assets/tessdata"]
path = app/assets/tessdata
url = https://github.com/tesseract-ocr/tessdata
[submodule "app/assets/tessdata_best"]
path = app/assets/tessdata_best
url = https://github.com/tesseract-ocr/tessdata_best
[submodule "app/assets/tessdata_fast"]
path = app/assets/tessdata_fast
url = https://github.com/tesseract-ocr/tessdata_fast

3
.sonarcloud.properties Normal file
View File

@ -0,0 +1,3 @@
sonar.issue.ignore.multicriteria=e1
sonar.issue.ignore.multicriteria.e1.ruleKey=javascript:S3504
sonar.issue.ignore.multicriteria.e1.resourceKey=**

11
CITATION.cff Normal file
View File

@ -0,0 +1,11 @@
cff-version: 1.2.0
message: "If you use this software, please cite it as below."
authors:
- family-names: "Go"
given-names: "Namhyeon"
orcid: "https://orcid.org/0009-0006-8421-0911"
title: "WelsonJS"
version: 0.2.7.12
doi: 10.5281/zenodo.11382384
date-released: 2024-05-29
url: "https://github.com/gnh1201/welsonjs"

70
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,70 @@
# Code of Conduct - WelsonJS
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to make participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, or to ban
temporarily or permanently any contributor for other behaviors that they deem
inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at <abuse@catswords.net>.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant](https://contributor-covenant.org/), version
[1.4](https://www.contributor-covenant.org/version/1/4/code-of-conduct/code_of_conduct.md) and
[2.0](https://www.contributor-covenant.org/version/2/0/code_of_conduct/code_of_conduct.md),
and was generated by [contributing-gen](https://github.com/bttger/contributing-gen).

147
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,147 @@
<!-- omit in toc -->
# Contributing to WelsonJS
First off, thanks for taking the time to contribute! ❤️
All types of contributions are encouraged and valued. See the [Table of Contents](#table-of-contents) for different ways to help and details about how this project handles them. Please make sure to read the relevant section before making your contribution. It will make it a lot easier for us maintainers and smooth out the experience for all involved. The community looks forward to your contributions. 🎉
> And if you like the project, but just don't have time to contribute, that's fine. There are other easy ways to support the project and show your appreciation, which we would also be very happy about:
> - Star the project
> - Tweet about it
> - Refer this project in your project's readme
> - Mention the project at local meetups and tell your friends/colleagues
<!-- omit in toc -->
## Table of Contents
- [Code of Conduct](#code-of-conduct)
- [I Have a Question](#i-have-a-question)
- [I Want To Contribute](#i-want-to-contribute)
- [Reporting Bugs](#reporting-bugs)
- [Suggesting Enhancements](#suggesting-enhancements)
- [Your First Code Contribution](#your-first-code-contribution)
- [Improving The Documentation](#improving-the-documentation)
- [Styleguides](#styleguides)
- [Commit Messages](#commit-messages)
- [Join The Project Team](#join-the-project-team)
## Code of Conduct
This project and everyone participating in it is governed by the
[WelsonJS Code of Conduct](https://github.com/gnh1201/welsonjs/blob/master/CODE_OF_CONDUCT.md).
By participating, you are expected to uphold this code. Please report unacceptable behavior
to <abuse@catswords.net>.
## I Have a Question
> If you want to ask a question, we assume that you have read the available [Documentation](https://catswords.social/@catswords_oss).
Before you ask a question, it is best to search for existing [Issues](https://github.com/gnh1201/welsonjs//issues) that might help you. In case you have found a suitable issue and still need clarification, you can write your question in this issue. It is also advisable to search the internet for answers first.
If you then still feel the need to ask a question and need clarification, we recommend the following:
- Open an [Issue](https://github.com/gnh1201/welsonjs//issues/new).
- Provide as much context as you can about what you're running into.
- Provide project and platform versions (nodejs, npm, etc), depending on what seems relevant.
We will then take care of the issue as soon as possible.
You might want to create a separate issue tag for questions and include it in this description. People should then tag their issues accordingly.
Depending on how large the project is, you may want to outsource the questioning, e.g. to Stack Overflow. You may add additional contact and information possibilities:
- ActivityPub
- Stack Overflow tag or Public Forums
- E-Mail List
## I Want To Contribute
> ### Legal Notice <!-- omit in toc -->
> When contributing to this project, you must agree that you have authored 100% of the content, that you have the necessary rights to the content and that the content you contribute may be provided under the project license.
### Reporting Bugs
<!-- omit in toc -->
#### Before Submitting a Bug Report
A good bug report shouldn't leave others needing to chase you up for more information. Therefore, we ask you to investigate carefully, collect information and describe the issue in detail in your report. Please complete the following steps in advance to help us fix any potential bug as fast as possible.
- Make sure that you are using the latest version.
- Determine if your bug is really a bug and not an error on your side e.g. using incompatible environment components/versions (Make sure that you have read the [documentation](https://catswords.social/@catswords_oss). If you are looking for support, you might want to check [this section](#i-have-a-question)).
- To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already a bug report existing for your bug or error in the [bug tracker](https://github.com/gnh1201/welsonjs/issues?q=label%3Abug).
- Also make sure to search the internet (including Stack Overflow) to see if users outside of the GitHub community have discussed the issue.
- Collect information about the bug:
- Stack trace (Traceback)
- OS, Platform and Version (Windows, Linux, macOS, x86, ARM)
- Version of the interpreter, compiler, SDK, runtime environment, package manager, depending on what seems relevant.
- Possibly your input and the output
- Can you reliably reproduce the issue? And can you also reproduce it with older versions?
<!-- omit in toc -->
#### How Do I Submit a Good Bug Report?
> You must never report security related issues, vulnerabilities or bugs including sensitive information to the issue tracker, or elsewhere in public. Instead sensitive bugs must be sent by email to <abuse@catswords.net>.
<!-- You may add a PGP key to allow the messages to be sent encrypted as well. -->
We use GitHub issues to track bugs and errors. If you run into an issue with the project:
- Open an [Issue](https://github.com/gnh1201/welsonjs//issues/new). (Since we can't be sure at this point whether it is a bug or not, we ask you not to talk about a bug yet and not to label the issue.)
- Explain the behavior you would expect and the actual behavior.
- Please provide as much context as possible and describe the *reproduction steps* that someone else can follow to recreate the issue on their own. This usually includes your code. For good bug reports you should isolate the problem and create a reduced test case.
- Provide the information you collected in the previous section.
Once it's filed:
- The project team will label the issue accordingly.
- A team member will try to reproduce the issue with your provided steps. If there are no reproduction steps or no obvious way to reproduce the issue, the team will ask you for those steps and mark the issue as `needs-repro`. Bugs with the `needs-repro` tag will not be addressed until they are reproduced.
- If the team is able to reproduce the issue, it will be marked `needs-fix`, as well as possibly other tags (such as `critical`), and the issue will be left to be [implemented by someone](#your-first-code-contribution).
<!-- You might want to create an issue template for bugs and errors that can be used as a guide and that defines the structure of the information to be included. If you do so, reference it here in the description. -->
### Suggesting Enhancements
This section guides you through submitting an enhancement suggestion for WelsonJS, **including completely new features and minor improvements to existing functionality**. Following these guidelines will help maintainers and the community to understand your suggestion and find related suggestions.
<!-- omit in toc -->
#### Before Submitting an Enhancement
- Make sure that you are using the latest version.
- Read the [documentation](https://catswords.social/@catswords_oss) carefully and find out if the functionality is already covered, maybe by an individual configuration.
- Perform a [search](https://github.com/gnh1201/welsonjs/issues) to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
- Find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset. If you're just targeting a minority of users, consider writing an add-on/plugin library.
<!-- omit in toc -->
#### How Do I Submit a Good Enhancement Suggestion?
Enhancement suggestions are tracked as [GitHub issues](https://github.com/gnh1201/welsonjs//issues).
- Use a **clear and descriptive title** for the issue to identify the suggestion.
- Provide a **step-by-step description of the suggested enhancement** in as many details as possible.
- **Describe the current behavior** and **explain which behavior you expected to see instead** and why. At this point you can also tell which alternatives do not work for you.
- You may want to **include screenshots and animated GIFs** which help you demonstrate the steps or point out the part which the suggestion is related to. You can use [this tool](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux. <!-- this should only be included if the project has a GUI -->
- **Explain why this enhancement would be useful** to most WelsonJS users. You may also want to point out the other projects that solved it better and which could serve as inspiration.
<!-- You might want to create an issue template for enhancement suggestions that can be used as a guide and that defines the structure of the information to be included. If you do so, reference it here in the description. -->
### Your First Code Contribution
Just Notepad, in Windows machine.
## Styleguides
### Commit Messages
Flexible. We will respect your style.
## Join The Project Team
Contact us:
* ActivityPub [@catswords_oss@catswords.social](https://catswords.social/@catswords_oss)
* abuse@catswords.net
## Attribution
This guide is based on the **contributing-gen**. [Make your own](https://github.com/bttger/contributing-gen)!

View File

@ -1,4 +0,0 @@
@echo off
reg add "HKCU\Software\Microsoft\Internet Explorer\Styles" /f
reg add "HKCU\Software\Microsoft\Internet Explorer\Styles" /v "MaxScriptStatements" /t REG_DWORD /d 0xFFFFFFFF /f

683
LICENSE
View File

@ -1,63 +1,674 @@
Microsoft Reciprocal License (MS-RL)
SPDX Short identifier: MS-RL
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software.
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
1. Definitions
The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law.
Preamble
A "contribution" is the original software, or any additions or changes to the software.
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
A "contributor" is any person that distributes its contribution under this license.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
"Licensed patents" are a contributor's patent claims that read directly on its contribution.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
2. Grant of Rights
(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
3. Conditions and Limitations
(A) Reciprocal Grants- For any file you distribute that contains code from the software (in source code or binary format), you must provide recipients the source code to that file along with a copy of this license, which license will govern that file. You may license other files that are entirely your own work and do not contain code from the software under any terms you choose.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
(B) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
(C) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
(D) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
(E) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
The precise terms and conditions for copying, distribution and
modification follow.
(F) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.
TERMS AND CONDITIONS
Microsoft 상호 라이선스(MS-RL)
SPDX 짧은 식별자: MS-RL
0. Definitions.
이 라이센스는 함께 제공되는 소프트웨어의 사용에 적용됩니다. 소프트웨어를 사용하는 경우 이 라이센스에 동의하는 것입니다. 라이센스에 동의하지 않으면 소프트웨어를 사용하지 마십시오.
"This License" refers to version 3 of the GNU General Public License.
1. 정의
"복제", "복제물", "파생 저작물" 및 "배포"라는 용어는 여기에서 미국 저작권법과 동일한 의미를 갖습니다.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"기여"은 원본 소프트웨어 또는 소프트웨어에 대한 추가 또는 변경 사항입니다.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
"기여자"는 이 라이선스에 따라 기여를 배포하는 모든 사람입니다.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
"라이선스 지적재산권"은 기여에 대해 직접 읽는 기여자의 지적재산권 주장입니다.
A "covered work" means either the unmodified Program or a work based
on the Program.
2. 권리 부여
(A) 저작권 부여 - 섹션 3의 라이선스 조건 및 제한 사항을 포함하여 이 라이선스의 조건에 따라 각 기여자는 자신의 기여를 복제하고 파생 작업을 준비할 수 있는 비독점적이고 전세계적인 로열티 없는 저작권 라이선스를 부여합니다. 기여 및 귀하가 만든 기여 또는 파생 작업을 배포합니다.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
(B) 지적재산권 부여 - 섹션 3의 라이선스 조건 및 제한 사항을 포함하여 이 라이선스의 조건에 따라 각 기여자는 라이선스가 부여된 지적재산권에 따라 귀하에게 비독점적이고 전 세계적으로 사용료가 없는 라이선스를 부여합니다. 여기에는 판매, 판매 제안, 수입 및 또는 소프트웨어에 대한 기여 또는 소프트웨어 기여의 파생물을 처분하는 행위를 포함합니다.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
3. 조건 및 제한
(A) 상호 부여 - 소프트웨어의 코드(소스코드 또는 바이너리 형식)가 포함된 배포하는 모든 파일의 경우 해당 파일에 적용되는 라이선스의 사본과 함께 해당 파일의 소스코드를 수신자에게 제공해야 합니다. . 귀하는 전적으로 귀하의 저작물이며 귀하가 선택한 조건에 따라 소프트웨어의 코드를 포함하지 않는 다른 파일에 라이선스를 부여할 수 있습니다.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
(B) 상표 사용권 없음 - 이 사용권은 기여자의 이름, 로고 또는 상표를 사용할 수 있는 권한을 부여하지 않습니다.
1. Source Code.
(C) 귀하가 소프트웨어에 의해 침해되었다고 주장하는 지적재산권에 대해 기여자에 대해 지적재산권 청구를 제기하는 경우 해당 기여자의 소프트웨어에 대한 귀하의 지적재산권 라이선스는 자동으로 종료됩니다.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
(D) 소프트웨어의 일부를 배포하는 경우 소프트웨어에 있는 모든 저작권, 지적재산권, 상표 및 귀속 고지를 보유해야 합니다.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
(E) 소프트웨어의 일부를 소스코드 형식으로 배포하는 경우 배포와 함께 이 라이센스의 전체 사본을 포함하여 이 라이센스 하에서만 그렇게 할 수 있습니다. 소프트웨어의 일부를 컴파일된 또는 개체 코드 형식으로 배포하는 경우 이 라이센스를 준수하는 라이센스 하에서만 배포할 수 있습니다.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
(F) 소프트웨어는 "있는 그대로" 사용이 허가됩니다. 당신은 그것을 사용할 위험을 감수합니다. 기여자는 명시적 보증, 보증 또는 조건을 제공하지 않습니다. 귀하는 현지 법률에 따라 이 라이선스가 변경할 수 없는 추가적인 소비자 권리를 가질 수 있습니다. 현지 법률에서 허용하는 범위 내에서 기여자는 상품성, 특정 목적에의 적합성 및 비침해성에 대한 묵시적 보증을 배제합니다.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

63
LICENSE_MSRL Normal file
View File

@ -0,0 +1,63 @@
Microsoft Reciprocal License (MS-RL)
SPDX Short identifier: MS-RL
This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software.
1. Definitions
The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law.
A "contribution" is the original software, or any additions or changes to the software.
A "contributor" is any person that distributes its contribution under this license.
"Licensed patents" are a contributor's patent claims that read directly on its contribution.
2. Grant of Rights
(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
3. Conditions and Limitations
(A) Reciprocal Grants- For any file you distribute that contains code from the software (in source code or binary format), you must provide recipients the source code to that file along with a copy of this license, which license will govern that file. You may license other files that are entirely your own work and do not contain code from the software under any terms you choose.
(B) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
(C) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.
(D) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.
(E) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
(F) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.
Microsoft 상호 라이선스(MS-RL)
SPDX 짧은 식별자: MS-RL
이 라이센스는 함께 제공되는 소프트웨어의 사용에 적용됩니다. 소프트웨어를 사용하는 경우 이 라이센스에 동의하는 것입니다. 라이센스에 동의하지 않으면 소프트웨어를 사용하지 마십시오.
1. 정의
"복제", "복제물", "파생 저작물" 및 "배포"라는 용어는 여기에서 미국 저작권법과 동일한 의미를 갖습니다.
"기여"은 원본 소프트웨어 또는 소프트웨어에 대한 추가 또는 변경 사항입니다.
"기여자"는 이 라이선스에 따라 기여를 배포하는 모든 사람입니다.
"라이선스 지적재산권"은 기여에 대해 직접 읽는 기여자의 지적재산권 주장입니다.
2. 권리 부여
(A) 저작권 부여 - 섹션 3의 라이선스 조건 및 제한 사항을 포함하여 이 라이선스의 조건에 따라 각 기여자는 자신의 기여를 복제하고 파생 작업을 준비할 수 있는 비독점적이고 전세계적인 로열티 없는 저작권 라이선스를 부여합니다. 기여 및 귀하가 만든 기여 또는 파생 작업을 배포합니다.
(B) 지적재산권 부여 - 섹션 3의 라이선스 조건 및 제한 사항을 포함하여 이 라이선스의 조건에 따라 각 기여자는 라이선스가 부여된 지적재산권에 따라 귀하에게 비독점적이고 전 세계적으로 사용료가 없는 라이선스를 부여합니다. 여기에는 판매, 판매 제안, 수입 및 또는 소프트웨어에 대한 기여 또는 소프트웨어 기여의 파생물을 처분하는 행위를 포함합니다.
3. 조건 및 제한
(A) 상호 부여 - 소프트웨어의 코드(소스코드 또는 바이너리 형식)가 포함된 배포하는 모든 파일의 경우 해당 파일에 적용되는 라이선스의 사본과 함께 해당 파일의 소스코드를 수신자에게 제공해야 합니다. . 귀하는 전적으로 귀하의 저작물이며 귀하가 선택한 조건에 따라 소프트웨어의 코드를 포함하지 않는 다른 파일에 라이선스를 부여할 수 있습니다.
(B) 상표 사용권 없음 - 이 사용권은 기여자의 이름, 로고 또는 상표를 사용할 수 있는 권한을 부여하지 않습니다.
(C) 귀하가 소프트웨어에 의해 침해되었다고 주장하는 지적재산권에 대해 기여자에 대해 지적재산권 청구를 제기하는 경우 해당 기여자의 소프트웨어에 대한 귀하의 지적재산권 라이선스는 자동으로 종료됩니다.
(D) 소프트웨어의 일부를 배포하는 경우 소프트웨어에 있는 모든 저작권, 지적재산권, 상표 및 귀속 고지를 보유해야 합니다.
(E) 소프트웨어의 일부를 소스코드 형식으로 배포하는 경우 배포와 함께 이 라이센스의 전체 사본을 포함하여 이 라이센스 하에서만 그렇게 할 수 있습니다. 소프트웨어의 일부를 컴파일된 또는 개체 코드 형식으로 배포하는 경우 이 라이센스를 준수하는 라이센스 하에서만 배포할 수 있습니다.
(F) 소프트웨어는 "있는 그대로" 사용이 허가됩니다. 당신은 그것을 사용할 위험을 감수합니다. 기여자는 명시적 보증, 보증 또는 조건을 제공하지 않습니다. 귀하는 현지 법률에 따라 이 라이선스가 변경할 수 없는 추가적인 소비자 권리를 가질 수 있습니다. 현지 법률에서 허용하는 범위 내에서 기여자는 상품성, 특정 목적에의 적합성 및 비침해성에 대한 묵시적 보증을 배제합니다.

236
README.md
View File

@ -1,85 +1,103 @@
# welsonjs
WelsonJS - Build a Windows desktop apps with JavaScript, HTML, and CSS based on WSH/HTA or GTK.
[![Buy me a coffee](https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png)](https://www.buymeacoffee.com/catswords/thanks-welsonjs-users)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fgnh1201%2Fwelsonjs.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fgnh1201%2Fwelsonjs?ref=badge_shield)
[![AppVeyor Status](https://ci.appveyor.com/api/projects/status/github/gnh1201/welsonjs?svg=true)](https://ci.appveyor.com/project/gnh1201/welsonjs)
[![DOI 10.5281/zenodo.11382384](https://zenodo.org/badge/DOI/10.5281/zenodo.11382384.svg)](https://doi.org/10.5281/zenodo.11382384)
[![ChatGPT available](https://img.shields.io/badge/ChatGPT-74aa9c?logo=openai&logoColor=white)](https://catswords-oss.rdbl.io/5719744820/5510319392)
[![Anthropic available](https://img.shields.io/badge/Anthropic-000000?logo=Anthropic&logoColor=white)](https://catswords-oss.rdbl.io/5719744820/5510319392)
[![Grok available](https://img.shields.io/badge/Grok-000000?logo=x&logoColor=white)](https://catswords-oss.rdbl.io/5719744820/5510319392)
[![Google Gemini available](https://img.shields.io/badge/Google%20Gemini-886FBF?logo=googlegemini&logoColor=fff)](https://catswords-oss.rdbl.io/5719744820/5510319392)
[![slideshare.net presentation](https://img.shields.io/badge/SlideShare-black?logo=slideshare)](https://www.slideshare.net/slideshow/welsonjs-javascript-framework-presentation-2024/276005486)
[![YouTube promotion video](https://img.shields.io/badge/YouTube-red?logo=youtube)](https://youtu.be/JavH7Dms8-U)
[![Discord chat](https://img.shields.io/discord/359930650330923008?logo=discord)](https://discord.gg/XKG5CjtXEj)
[![Open to work](https://img.shields.io/badge/%23-OPENTOWORK-green)](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.
![A Cover Image: Windows in 1999](https://ics.catswords.net/cover.png)
Now, You can build a 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)
* :kissing_cat: [Download Latest WelsonJS Launcher (ics.catswords.net)](https://ics.catswords.net/welsonjs_launcher_latest.zip)
* :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
* :octocat: [GitHub Sponsors](https://github.com/sponsors/gnh1201), :coffee: [Buy me a coffee](https://buymeacoffee.com/catswords)
* <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="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="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
* **Operating Systems**: Windows XP SP3 or later (Currently, Windows 11 24H2)
* For systems running Windows 2000 or earlier versions (e.g., 95, 98, Me), please contact us separately.
## 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](app/assets/img/structure.png)
![The structure of the WelsonJS framework can be extended based on whether it operates in a console (command prompt) environment, a GUI (with HTML/CSS) environment, or a service environment, with the `app.js` file at its core.](https://ics.catswords.net/structure.png)
## Specifications
- ES5(ECMAScript 5), XML, JSON, YAML compatibility
- [github:zloirock/core-js](https://github.com/zloirock/core-js)
- [github:douglascrockford/JSON-js](https://github.com/douglascrockford/JSON-js) (aka. JSON2.js)
- [github:nodeca/js-yaml](https://github.com/nodeca/js-yaml)
- HTML5, CSS3 compatibility
- [github:aFarkas/html5shiv](https://github.com/aFarkas/html5shiv)
- [github:parndt/jquery-html5-placeholder-shim](https://github.com/parndt/jquery-html5-placeholder-shim)
- [github:scottjehl/Respond](https://github.com/scottjehl/Respond)
- [github:keithclark/selectivizr](https://github.com/keithclark/selectivizr)
- [github:arv/ExplorerCanvas](https://github.com/arv/ExplorerCanvas)
- [github:etianen/html5media](https://github.com/etianen/html5media)
- [github:Modernizr/Modernizr](https://github.com/Modernizr/Modernizr)
- Default CSS Framework
- [github:jslegers/cascadeframework](https://github.com/jslegers/cascadeframework)
- Included libraries
- [jQuery](https://jquery.com/)
- [jQuery UI](https://jqueryui.com/)
- [github:kamranahmedse/jquery-toast-plugin](https://github.com/kamranahmedse/jquery-toast-plugin)
- [github:hiddentao/squel](https://github.com/hiddentao/squel)
- [github:BorisMoore/jsrender](https://github.com/BorisMoore/jsrender)
- [Includes binaries](https://github.com/gnh1201/welsonjs/blob/master/bin/README.MD)
- [module.exports](https://nodejs.org/en/knowledge/getting-started/what-is-require/), CommonJS, UMD compatibility
- [NPM](https://www.npmjs.com/) compatibility
- [CoffeeScript 2](https://coffeescript.org/)/[LiveScript](https://livescript.net/) compatibility
- [TypeScript](https://www.typescriptlang.org/) compatibility
- Ready to use on Windows machine immediately. No require additional softwares installation.
* 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.**
* **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) on the code editor.
* 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)
* 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)
* Classical CSS Frameworks: [cascadeframework](https://github.com/jslegers/cascadeframework), [golden-layout](https://github.com/golden-layout/golden-layout)
* WYSIWYG HTML Editor: [summernote](https://github.com/summernote/summernote)
* 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)
* 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
* 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)
* RPC(Remote Procedure Call) protocol clients: [gRPC](https://grpc.io/), [JSON-RPC 2.0](https://www.jsonrpc.org/specification)
* 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)
* 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)
* Generative AI integrations: [Multiple LLM and sLLM](https://catswords-oss.rdbl.io/5719744820/5510319392) (e.g., ChatGPT, Claude, ...)
* Aviation Data integrations: [AviationStack](https://aviationstack.com?utm_source=FirstPromoter&utm_medium=Affiliate&fpr=namhyeon71), [SearchApi Google Flight](https://www.searchapi.io/?via=namhyeon)
* VM infrastructure tool integrations: [OVFTool for Broadcom/VMware infrastructures](https://developer.broadcom.com/tools/open-virtualization-format-ovf-tool/latest)
* Everything you can imagine.
## Included libraries
- lib/std (Standard library)
- lib/system (System library)
- lib/base64 (BASE64 Encode and Decode)
- lib/db (Database interface)
- lib/file (File I/O interface)
- lib/http (HTTP interface)
- lib/json (JSON Encode and Decode)
- lib/registry (Windows Registry interface)
- lib/security (Security Policy interface)
- lib/sendmail (Sendmail interface with 3rdparty)
- lib/shell (Command Prompt interface)
- lib/timer (`setTimeout` polyfills)
- lib/powershell (Windows Powershell interface)
- lib/service (Windows Service interface)
- lib/oldbrowser (ES5/ES6, HTML/JS/CSS compatibility)
- 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/shadowsocks ([Shadowsocks](https://shadowsocks.org/) interface)
- lib/excel (Microsoft Excel interface)
- lib/vbscript (VBScript interface)
- lib/wintap (Windows-TAP interface)
- lib/tun2socks (TUN2SOCKS interface)
- lib/hosts (Hosts file interface)
- lib/gtk (GTK/GladeXML server GUI interface)
- lib/chrome (Chrome Web Browser Debugging interface)
- lib/toolkit (`WelsonJS.Toolkit` native component)
- lib/pipe-ipc (PIPE-based IPC(Inter-Process Communication) implementation)
## Make your own `sayhello` example
## Quick start
### 1. Write a file `lib/sayhello.js`
```
exports.VERSIONINFO = "SayHello Library (sayhello.js) version 0.1
exports.global = global;
exports.require = global.require;
exports.say = function() {
```js
// 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;
```
### 2. Write a file `sayhello.js`
```
```js
// sayhello.js
var SayHello = require("lib/sayhello");
function main() {
@ -91,39 +109,73 @@ function main() {
exports.main = main;
```
### 3. Execute file on the command prompt
```
C:\Users\John\Documents\GitHub\welsonjs> cscript app.js sayhello
### 3. Execute script on the console
```cmd
C:\Users\JohnDoe\Documents\GitHub\welsonjs> cscript app.js sayhello
calling say()
hello
ended say()
```
## How to make your own setup file
- Please check `setup.iss` file it could be compile with [Inno Setup](https://jrsoftware.org/isinfo.php)
## How to release my application?
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).
* **Build a setup file**: Use [Inno Setup](https://jrsoftware.org/isinfo.php). The setup profile (the `setup.iss` file) is already included.
* **Copy all directories and files**: This is the simplest and most straightforward method.
## Screenshots
![Screenshot 1](app/assets/img/screenshot.png)
![(Screenshot 1) GUI environment](https://ics.catswords.net/screenshot.png)
## Thanks!
![Thanks 1](app/assets/img/thanks.png)
![(Screenshot 2) Command-line environment](https://ics.catswords.net/screenshot2.png)
- https://www.facebook.com/javascript4u/posts/1484014618472735
- https://python5.com/q/xtbsqjxb
![(Screenshot 3) WelsonJS with Microsoft Excel](https://ics.catswords.net/screenshot3.png)
## Related projects
- [gnh1201/wsh-js-gtk](https://github.com/gnh1201/wsh-js-gtk) - GTK GUI ported to Windows Scripting Host - Javascript (Microsoft JScript) (wsh-js)
- [gnh1201/wsh-json](https://github.com/gnh1201/wsh-json) - JSON stringify/parse (encode/decode) for Windows Scripting Host
- [redskyit/wsh-appjs](https://github.com/redskyit/wsh-appjs) - require-js and app framework for Windows Scripting Host JavaScript
- [JohnLaTwC's gist](https://gist.github.com/JohnLaTwC/4315bbbd89da0996f5c08c032b391799) - JavaScript RAT
- [JSMan-/JS-Framework](https://github.com/JSMan-/JS-Framework) - No description
- [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
- [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
![(Screenshot 4) Write a Windows Services with JavaScript](https://ics.catswords.net/screenshot4.png)
## Image stocks
- [7418_blocks_color_modules_rgb_square_icon](https://www.iconfinder.com/icons/7418/blocks_color_modules_rgb_square_icon) (Icon File) - Sergio Sanchesz Lopez, Futurosoft
![(Screenshot 5) Template Matching on the computer screen](https://ics.catswords.net/screenshot5.png)
## Contact me
- abuse@catswords.net
![(Screenshot 6) The Launcher for WelsonJS Application Packages](https://ics.catswords.net/screenshot6.png)
![(Screenshot 7) Microsoft Monaco Editor on WelsonJS Launcher](https://ics.catswords.net/screenshot7.png)
## Thanks to
* :heart: Artwork (Logo image): [@druidesse](https://github.com/druidesse)
* :heart: Artwork (Cover image): [@_bag0@x.com](https://x.com/_bag0)
* :heart: Special Contributors: [@hcho3](https://github.com/hcho3), :octocat: [GitHub Sponsors](https://github.com/sponsors/gnh1201)
* :sunglasses: Heavy-industry specialized CSP(Cloud Service Provider) in Republic of Korea - Use case establishment
* :sunglasses: Live-commerce specialized online advertisement companies in Republic of Korea - Use case establishment
* :sunglasses: Information security companies in Republic of Korea - Use case establishment
* :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/)
* :eyes: [morioh.com](https://morioh.com/a/23c427a82bf1/build-a-windows-desktop-apps-with-javascript-html-and-css)
* :eyes: CSDN
* :eyes: Qiita - Knowledge-base about WSH environment
* :sunglasses: Redsky Software - PoC(Proof of Concept) of the CommonJS on WSH environment
* :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.
* :eyes: Fediverse
* :eyes: [Hacker News](https://news.ycombinator.com/item?id=41316782)
* :eyes: [WebToolsWeekly](https://webtoolsweekly.com/archives/issue-585/)
* :eyes: [GeekNews](https://news.hada.io/weekly/202441) in GeekNews Weekly (2024-09-30 ~ 2024-10-06)
* :eyes: [daily.dev](https://app.daily.dev/posts/js-libraries-svg-tools-json-databases-8quregz3a)
* :eyes: [PitchHut](https://www.pitchhut.com/project/proj_Ya136OLSW5at)
* :eyes: [Disquiet](https://dis.qa/nv6T6)
## Report abuse
* [GitHub Security Advisories (gnh1201/welsonjs)](https://github.com/gnh1201/welsonjs/security)
* [abuse@catswords.net](mailto:abuse@catswords.net)
## Join the community
I am always open. Collaboration, opportunities, and community activities are all welcome.
* 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
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fgnh1201%2Fwelsonjs.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fgnh1201%2Fwelsonjs?ref=badge_large)

View File

@ -1,20 +0,0 @@
# REGASM for WelsonJS
In general, the location of REGASM is as follows.
```
C:\Windows\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe
```
Or it may vary depending on the version.
## How to register .NET COM/DLL component
Example:
```
C:\Windows\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe /codebase WelsonJS.Toolkit.dll
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\RegAsm.exe /codebase WelsonJS.Toolkit.dll
```
Thank you.

View File

@ -1,27 +1,63 @@
# Security Note for WelsonJS
## License
The WelsonJS project is available under either the GPLv3 or MS-RL opensource licenses. If the GPLv3 license is not compatible with Microsoft products, the MS-RL license applies; otherwise, the GPLv3 license is used. Under these licenses, if you distribute modified versions of this project's source code to third parties, you may be required to disclose the source code. For more details, please refer to the `LICENSE` and `LICENSE_MSRL` files.
## Caution
This repository includes recent cases on how to access Windows APIs and functions at the JavaScript level.
This repository contains information on accessing Windows APIs and functions in the JavaScript runtime, along with recent case studies. While this can provide a flexible development environment for anyone, it can also be misused for malicious purposes. Please be aware that using this project to create abuse tools, such as for DoS attacks, may result in legal consequences in your country. We encourage you to use this project only for creating web technology-based applications, like Electron, or legally permitted testing tools.
This way can provide a flexible development environment for anyone, but it also applies to those with malicious purposes.
## Known Use Cases
WelsonJS is typically used for the following purposes:
Using this project to create an abuse tools (e.g. DoS attack) may be subject to punishment in your country.
* Testing web accessibility and compliance, including adherence to W3C standards (WEB-ARIA, WCAG), national laws (ADA/DDA, GDPR), and other relevant regulations.
* Exploring vulnerabilities of equipment within the local network.
* Improving the availability of VPN or proxy clients.
* Building automation, CI/CD (Continuous Integration/Continuous Delivery), DevOps, and SecOps.
* Asset evaluation (e.g., obtaining purchase history from online shopping and delivery websites).
* Online video streaming quality testing and improvement.
* Office automation and integration with LLM-based AI (e.g., ChatGPT) services.
Please use it only to create a web technology based application similar to Electron or legally testing tool.
## Notes
1. If you plan to use WelsonJS for a purpose other than those mentioned above, please contact us beforehand.
2. If you are looking for ways to use WelsonJS more efficiently, referencing the [LOLBAS (Living Off The Land Binaries and Scripts)](https://lolbas-project.github.io/) list can be helpful.
## Known use cases
In general, WelsonJS is used in the following situations.
## Guidelines
* Test web accessibility and compliance: e.g. W3C standards(WEB-ARIA, WCAG), The national laws(ADA/DDA, GDPR)
* Explore vulnerabilities of equipment within the local network
* Improve availablity of a clients of VPN or Proxy
* Build automation, CD/CI(Continuous Integration/Continuous Delivery), DevOps, SecOps
### Use of Online Shopping and Delivery Websites
We are aware of cases where WelsonJS has been used to access the websites of online shopping or delivery companies for asset valuation. This is a good use case, but there have been reports of website downtime caused by excessive concurrent requests. Please exercise caution and avoid excessive simultaneous executions.
Note 1: If you deviate from the previous case mentioned above, please contact us before using it.
### Use for Online Video Streaming Quality Testing and Improvement
We are aware of cases where WelsonJS is used for video streaming quality testing and improvement. It should be used solely for expert-level streaming quality testing, often referred to by terms like 4K, 8K, HD, FHD, UHD, 720p, 1080p, etc. For such purposes, it is recommended to use videos provided by television manufacturers (e.g., LG, Samsung) or graphics card manufacturers (e.g., NVIDIA, AMD) specifically for testing purposes. It is essential to avoid using videos that contain content not legally permitted in your region. The WelsonJS developers and maintainers take no responsibility for the use of videos containing illegal content.
Note 2: A similar approach that WelsonJS uses has been called `LOLBins` in the cyber security community since 2018. This is not intended to be but you will get useful hints you need for extensions.
### Use for Scientific Research Institutes
WelsonJS is designed for flexible industrial facility control (a.k.a. Industrial Scripting) in environments where modifying compiled binaries is restricted. Parts or all of this project's source code may be found in use within scientific research institutes. In such cases, appropriate safety measures tailored to the specific application area may be required. If support is needed for these applications, please do not hesitate to contact us.
### Use for Security Testing
We are aware of instances where WelsonJS has been used by legitimate cybersecurity firms to discover and test vulnerabilities (such as credential stuffing) in IoT devices. If you intend to use WelsonJS as a security testing tool, it should be done in a controlled environment that complies with legal regulations.
### Use for Cloud Monitoring
WelsonJS is a project inspired by the requirements of a cloud service provider to develop lightweight software (e.g., agents) for collecting metrics on Windows systems. While using WelsonJS for this purpose is desirable, ensuring security in the server-client communication is entirely the responsibility of the user.
## 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:
* DOI [10.5281/zenodo.11382384](https://zenodo.org/doi/10.5281/zenodo.11382384)(2024) (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<sup>(정보통신산업진흥원)</sup>, 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)
* "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
If you find any abuse cases of this project, please report it.
* [GitHub Security Advisories](https://github.com/gnh1201/welsonjs/security)
* [abuse@catswords.net](mailto:abuse@catswords.net)
* abuse@catswords.net
## Join the community
* 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.

Binary file not shown.

View File

@ -0,0 +1,261 @@
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;
}
}

View File

@ -0,0 +1,295 @@
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);
}
}
}
}
}

View File

@ -0,0 +1,120 @@
<?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>

View File

@ -0,0 +1,89 @@
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;
}
}

View File

@ -0,0 +1,56 @@
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);
}
}
}
}

View File

@ -0,0 +1,120 @@
<?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>

View File

@ -0,0 +1,25 @@
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);
}
}

View File

@ -0,0 +1,170 @@
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;
}
}

View File

@ -0,0 +1,141 @@
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;
}
}
}

View File

@ -0,0 +1,120 @@
<?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>

View File

@ -0,0 +1,279 @@
namespace WelsonJS.Launcher
{
partial class MainForm
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.btnRunFromZipFile = new System.Windows.Forms.Button();
this.btnRunFromExternalLink = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.linkLabel1 = new System.Windows.Forms.LinkLabel();
this.cbUseSpecificScript = new System.Windows.Forms.CheckBox();
this.txtUseSpecificScript = new System.Windows.Forms.TextBox();
this.cbInteractiveServiceApp = 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();
//
// btnRunFromZipFile
//
this.btnRunFromZipFile.Image = global::WelsonJS.Launcher.Properties.Resources.icon_zip_128;
this.btnRunFromZipFile.Location = new System.Drawing.Point(24, 67);
this.btnRunFromZipFile.Name = "btnRunFromZipFile";
this.btnRunFromZipFile.Size = new System.Drawing.Size(200, 200);
this.btnRunFromZipFile.TabIndex = 0;
this.btnRunFromZipFile.Text = "From ZIP file...";
this.btnRunFromZipFile.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.btnRunFromZipFile.UseVisualStyleBackColor = true;
this.btnRunFromZipFile.Click += new System.EventHandler(this.btnRunFromZipFile_Click);
//
// btnRunFromExternalLink
//
this.btnRunFromExternalLink.Image = global::WelsonJS.Launcher.Properties.Resources.icon_link_128;
this.btnRunFromExternalLink.Location = new System.Drawing.Point(230, 67);
this.btnRunFromExternalLink.Name = "btnRunFromExternalLink";
this.btnRunFromExternalLink.Size = new System.Drawing.Size(200, 200);
this.btnRunFromExternalLink.TabIndex = 1;
this.btnRunFromExternalLink.Text = "From external link...";
this.btnRunFromExternalLink.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.btnRunFromExternalLink.UseVisualStyleBackColor = true;
this.btnRunFromExternalLink.Click += new System.EventHandler(this.btnRunFromExternalLink_Click);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(24, 41);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(312, 12);
this.label1.TabIndex = 2;
this.label1.Text = "Choose the location of WelsonJS application package.";
//
// linkLabel1
//
this.linkLabel1.AutoSize = true;
this.linkLabel1.Location = new System.Drawing.Point(24, 345);
this.linkLabel1.Name = "linkLabel1";
this.linkLabel1.Size = new System.Drawing.Size(219, 12);
this.linkLabel1.TabIndex = 3;
this.linkLabel1.TabStop = true;
this.linkLabel1.Text = "https://github.com/gnh1201/welsonjs";
this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
//
// cbUseSpecificScript
//
this.cbUseSpecificScript.AutoSize = true;
this.cbUseSpecificScript.Location = new System.Drawing.Point(26, 281);
this.cbUseSpecificScript.Name = "cbUseSpecificScript";
this.cbUseSpecificScript.Size = new System.Drawing.Size(184, 16);
this.cbUseSpecificScript.TabIndex = 4;
this.cbUseSpecificScript.Text = "I want to use specific script ";
this.cbUseSpecificScript.UseVisualStyleBackColor = true;
this.cbUseSpecificScript.CheckedChanged += new System.EventHandler(this.cbUseSpecificScript_CheckedChanged);
//
// txtUseSpecificScript
//
this.txtUseSpecificScript.Enabled = false;
this.txtUseSpecificScript.Location = new System.Drawing.Point(214, 278);
this.txtUseSpecificScript.Name = "txtUseSpecificScript";
this.txtUseSpecificScript.Size = new System.Drawing.Size(110, 21);
this.txtUseSpecificScript.TabIndex = 5;
//
// cbInteractiveServiceApp
//
this.cbInteractiveServiceApp.AutoSize = true;
this.cbInteractiveServiceApp.Location = new System.Drawing.Point(26, 305);
this.cbInteractiveServiceApp.Name = "cbInteractiveServiceApp";
this.cbInteractiveServiceApp.Size = new System.Drawing.Size(254, 16);
this.cbInteractiveServiceApp.TabIndex = 6;
this.cbInteractiveServiceApp.Text = "This is an Interactive Service Application";
this.cbInteractiveServiceApp.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
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(461, 382);
this.Controls.Add(this.cbInteractiveServiceApp);
this.Controls.Add(this.txtUseSpecificScript);
this.Controls.Add(this.cbUseSpecificScript);
this.Controls.Add(this.linkLabel1);
this.Controls.Add(this.label1);
this.Controls.Add(this.btnRunFromExternalLink);
this.Controls.Add(this.btnRunFromZipFile);
this.Controls.Add(this.menuStrip1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Icon = global::WelsonJS.Launcher.Properties.Resources.favicon;
this.MainMenuStrip = this.menuStrip1;
this.MaximizeBox = false;
this.Name = "MainForm";
this.Text = "WelsonJS Application Launcher";
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
this.contextMenuStrip1.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button btnRunFromZipFile;
private System.Windows.Forms.Button btnRunFromExternalLink;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.LinkLabel linkLabel1;
private System.Windows.Forms.CheckBox cbUseSpecificScript;
private System.Windows.Forms.TextBox txtUseSpecificScript;
private System.Windows.Forms.CheckBox cbInteractiveServiceApp;
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;
}
}

View File

@ -0,0 +1,275 @@
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Security.Principal;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WelsonJS.Launcher
{
public partial class MainForm : Form
{
private string workingDirectory;
private string instanceId;
private string entryFileName;
private string scriptName;
public MainForm()
{
entryFileName = "bootstrap.bat";
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()
{
label1.Text = "Choose the location of WelsonJS application package.";
btnRunFromZipFile.Enabled = true;
btnRunFromExternalLink.Enabled = true;
cbUseSpecificScript.Enabled = true;
cbInteractiveServiceApp.Enabled = true;
if (cbUseSpecificScript.Checked)
{
txtUseSpecificScript.Enabled = true;
}
}
private void DisableUI()
{
label1.Text = "Please wait...";
btnRunFromZipFile.Enabled = false;
btnRunFromExternalLink.Enabled = false;
cbUseSpecificScript.Enabled = false;
cbInteractiveServiceApp.Enabled = false;
txtUseSpecificScript.Enabled = false;
}
private void SafeInvoke(Action action)
{
if (InvokeRequired)
{
Invoke(action);
}
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);
}
}
}
private void ExtractAndRun(string filePath)
{
instanceId = Guid.NewGuid().ToString();
workingDirectory = Program.GetWorkingDirectory(instanceId);
scriptName = txtUseSpecificScript.Text;
Task.Run(() =>
{
try
{
// If exists, delete all
if (Directory.Exists(workingDirectory))
{
Directory.Delete(workingDirectory, true);
}
// try to extact ZIP file
ZipFile.ExtractToDirectory(filePath, workingDirectory);
// record the first deploy time
RecordFirstDeployTime(workingDirectory);
// follow the sub-directory
workingDirectory = Program.GetWorkingDirectory(instanceId, true);
// Run the appliction
Program.RunCommandPrompt(workingDirectory, entryFileName, scriptName, cbUseSpecificScript.Checked, cbInteractiveServiceApp.Checked);
}
catch (Exception ex)
{
SafeInvoke(() =>
{
MessageBox.Show("Error: " + ex.Message);
});
}
// Enable UI
SafeInvoke(() => {
EnableUI();
});
});
DisableUI();
}
private void RecordFirstDeployTime(string directory)
{
try
{
string filePath = Path.Combine(directory, ".welsonjs_first_deploy_time");
string text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
File.WriteAllText(filePath, text);
}
catch (Exception ex)
{
throw new Exception($"Failed to record first deploy time: {ex.Message}");
}
}
private bool IsInAdministrator()
{
try
{
WindowsPrincipal wp = new WindowsPrincipal(WindowsIdentity.GetCurrent());
return wp.IsInRole(WindowsBuiltInRole.Administrator);
}
catch
{
return false;
}
}
private void cbUseSpecificScript_CheckedChanged(object sender, EventArgs e)
{
txtUseSpecificScript.Enabled = cbUseSpecificScript.Checked;
}
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
Program.OpenWebBrowser(Program.GetAppConfig("RepositoryUrl"));
}
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"));
}
}
}

View File

@ -0,0 +1,129 @@
<?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>
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="notifyIcon1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>134, 17</value>
</metadata>
<metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>249, 17</value>
</metadata>
</root>

View File

@ -0,0 +1,191 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using System.Configuration;
namespace WelsonJS.Launcher
{
internal static class Program
{
static Mutex mutex;
public static ResourceServer resourceServer;
[STAThread]
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.SetCompatibleTextRenderingDefault(false);
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;
}
}
}

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
// 이러한 특성 값을 변경하세요.
[assembly: AssemblyTitle("WelsonJS.Launcher")]
[assembly: AssemblyDescription("Launcher for WelsonJS Application Packages")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Catswords")]
[assembly: AssemblyProduct("WelsonJS")]
[assembly: AssemblyCopyright("Catswords OSS, GPLv3 or Ms-RL")]
[assembly: AssemblyTrademark("WelsonJS")]
[assembly: AssemblyCulture("")]
// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요.
[assembly: ComVisible(false)]
// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
[assembly: Guid("4074d413-195c-45e9-9e63-0d07914187b8")]
// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.
//
// 주 버전
// 부 버전
// 빌드 번호
// 수정 버전
//
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
// 기본값으로 할 수 있습니다.
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.2.7.54")]
[assembly: AssemblyFileVersion("0.2.7.54")]

View File

@ -0,0 +1,289 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 이 코드는 도구를 사용하여 생성되었습니다.
// 런타임 버전:4.0.30319.42000
//
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
// 이러한 변경 내용이 손실됩니다.
// </auto-generated>
//------------------------------------------------------------------------------
namespace WelsonJS.Launcher.Properties {
using System;
/// <summary>
/// 지역화된 문자열 등을 찾기 위한 강력한 형식의 리소스 클래스입니다.
/// </summary>
// 이 클래스는 ResGen 또는 Visual Studio와 같은 도구를 통해 StronglyTypedResourceBuilder
// 클래스에서 자동으로 생성되었습니다.
// 멤버를 추가하거나 제거하려면 .ResX 파일을 편집한 다음 /str 옵션을 사용하여 ResGen을
// 다시 실행하거나 VS 프로젝트를 다시 빌드하십시오.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// 이 클래스에서 사용하는 캐시된 ResourceManager 인스턴스를 반환합니다.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("WelsonJS.Launcher.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// 이 강력한 형식의 리소스 클래스를 사용하여 모든 리소스 조회에 대해 현재 스레드의 CurrentUICulture 속성을
/// 재정의합니다.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <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>
/// 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>
/// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다.
/// </summary>
internal static System.Drawing.Bitmap icon_link_128 {
get {
object obj = ResourceManager.GetObject("icon_link_128", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <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>
/// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다.
/// </summary>
internal static System.Drawing.Bitmap icon_zip_128 {
get {
object obj = ResourceManager.GetObject("icon_zip_128", resourceCulture);
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);
}
}
}
}

View File

@ -0,0 +1,193 @@
<?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>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<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>
</data>
<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>
</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>
</root>

View File

@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 이 코드는 도구를 사용하여 생성되었습니다.
// 런타임 버전:4.0.30319.42000
//
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
// 이러한 변경 내용이 손실됩니다.
// </auto-generated>
//------------------------------------------------------------------------------
namespace WelsonJS.Launcher.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.10.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

View File

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@ -0,0 +1,500 @@
// 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.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;
}
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; }
}
}

View File

@ -0,0 +1,214 @@
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; }
}
}

View File

@ -0,0 +1,42 @@
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);
}
}
}
}

View File

@ -0,0 +1,343 @@
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);
}
}
}

View File

@ -0,0 +1,77 @@
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");
}
}
}

View File

@ -0,0 +1,103 @@
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();
}
}
}

View File

@ -0,0 +1,60 @@
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);
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 974 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 837 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 796 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,169 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{4074D413-195C-45E9-9E63-0D07914187B8}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>WelsonJS.Launcher</RootNamespace>
<AssemblyName>WelsonJS.Launcher</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>favicon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<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.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<Compile Include="IResourceTool.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">
<SubType>Form</SubType>
</Compile>
<Compile Include="MainForm.Designer.cs">
<DependentUpon>MainForm.cs</DependentUpon>
</Compile>
<Compile Include="Program.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" />
<EmbeddedResource Include="EnvForm.resx">
<DependentUpon>EnvForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="InstancesForm.resx">
<DependentUpon>InstancesForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<SubType>Designer</SubType>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="GlobalSettingsForm.resx">
<DependentUpon>GlobalSettingsForm.cs</DependentUpon>
</EmbeddedResource>
<None Include="app.config" />
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="Resources\icon_link_128.png" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\icon_zip_128.png" />
</ItemGroup>
<ItemGroup>
<None 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>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<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"/>
</appSettings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/>
</startup>
</configuration>

View File

@ -0,0 +1,597 @@
<!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
}) {
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: 'btnDnsQuery', icon: 'mif-earth', caption: 'DNS', onClick: onQueryDnsClick }
];
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;
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(`/*\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(`/*\n${responseText}\n*/`);
pushPromptMessage("system", responseText);
}).catch(error => {
console.error(error);
});
};
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
}),
_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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

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

View File

@ -0,0 +1,30 @@
// ElasticsearchClient.cs
// https://github.com/gnh1201/welsonjs
using RestSharp.Authenticators;
using RestSharp;
namespace WelsonJS.Service
{
public class ElasticsearchClient
{
private readonly RestClient client;
public ElasticsearchClient(string baseUrl, string username, string password)
{
var options = new RestClientOptions(baseUrl)
{
Authenticator = new HttpBasicAuthenticator(username, password)
};
client = new RestClient(options);
}
public RestResponse IndexDocument(string indexName, object document)
{
var request = new RestRequest($"/{indexName}/_doc", Method.Post);
request.AddHeader("Content-Type", "application/json");
request.AddJsonBody(document);
return client.Execute(request);
}
}
}

View File

@ -0,0 +1,255 @@
// FileEventMonitor.cs
// Namhyeon Go <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
using ClamAV.Net.Client;
using ClamAV.Net.Client.Results;
using Microsoft.Extensions.Logging;
using System;
using System.Diagnostics.Eventing.Reader;
using System.ServiceProcess;
using System.Threading.Tasks;
namespace WelsonJS.Service
{
public class FileEventMonitor
{
private EventLogWatcher eventLogWatcher;
private ServiceMain parent;
private ILogger logger;
private enum EventType: int
{
FileCreate = 11,
NetworkConnection = 3,
RegistryEvent_1 = 12,
RegistryEvent_2 = 13,
RegistryEvent_3 = 14
};
private enum FileCreateEvent: int {
RuleName,
UtcTime,
ProcessGuid,
ProcessId,
Image,
TargetFilename,
CreationUtcTime,
User
};
private enum NetworkConnectionEvent: int
{
RuleName,
UtcTime,
ProcessGuid,
ProcessId,
Image,
User,
Protocol,
Initiated,
SourceIsIpv6,
SourceIp,
SourceHostname,
SourcePort,
SourcePortName,
DestinationIsIpv6,
DestinationIp,
DestinationHostname,
DestinationPort,
DestinationPortName,
};
private enum RegistryEvent: int
{
RuleName,
EventType,
UtcTime,
ProcessGuid,
ProcessId,
Image,
TargetObject,
Details,
User
}
private string clamAvConenctionString;
private IClamAvClient clamAvClient;
public FileEventMonitor(ServiceBase _parent, string workingDirectory, ILogger _logger)
{
parent = (ServiceMain)_parent;
logger = _logger;
try
{
clamAvConenctionString = parent.ReadSettingsValue("CLAMAV_HOST");
}
catch (Exception ex)
{
clamAvConenctionString = "tcp://127.0.0.1:3310";
logger.LogInformation($"Failed to read the address because of {ex.Message}. Set default: {clamAvConenctionString}");
}
ConnectToClamAv().Start();
}
public void Start()
{
try
{
string query = @"<QueryList>
<Query Id='0' Path='Microsoft-Windows-Sysmon/Operational'>
<Select Path='Microsoft-Windows-Sysmon/Operational'>*[System/EventID=11 or System/EventID=3 or System/EventID=12 or System/EventID=13 or System/EventID=14]</Select>
</Query>
</QueryList>";
EventLogQuery eventLogQuery = new EventLogQuery("Microsoft-Windows-Sysmon/Operational", PathType.LogName, query);
eventLogWatcher = new EventLogWatcher(eventLogQuery);
eventLogWatcher.EventRecordWritten += new EventHandler<EventRecordWrittenEventArgs>(OnEventRecordWritten);
eventLogWatcher.Enabled = true;
}
catch (Exception ex)
{
logger.LogInformation($"Could not reach to the Sysmon service: {ex.Message}");
}
}
public void Stop()
{
if (eventLogWatcher != null)
{
try
{
eventLogWatcher.Dispose();
eventLogWatcher = null;
}
catch (Exception)
{
eventLogWatcher = null;
}
}
}
private void OnEventRecordWritten(object sender, EventRecordWrittenEventArgs e)
{
if (e.EventRecord != null)
{
int eventId = e.EventRecord.Id;
try
{
switch (eventId)
{
case (int)EventType.FileCreate:
{
string ruleName = e.EventRecord.Properties[(int)FileCreateEvent.RuleName]?.Value?.ToString();
string processId = e.EventRecord.Properties[(int)FileCreateEvent.ProcessId]?.Value?.ToString();
string image = e.EventRecord.Properties[(int)FileCreateEvent.Image]?.Value?.ToString();
string fileName = e.EventRecord.Properties[(int)FileCreateEvent.TargetFilename]?.Value?.ToString();
logger.LogInformation($"> Detected the file creation: {fileName}");
logger.LogInformation(parent.DispatchServiceEvent("fileCreated", new string[] {
ruleName,
processId,
image,
fileName
}));
if (clamAvClient != null)
{
logger.LogInformation($"> Starting the ClamAV scan: {fileName}");
Task.Run(async () =>
{
await ScanWithClamAv(fileName);
});
}
break;
}
case (int)EventType.NetworkConnection:
{
string ruleName = e.EventRecord.Properties[(int)NetworkConnectionEvent.RuleName]?.Value?.ToString();
string processId = e.EventRecord.Properties[(int)NetworkConnectionEvent.ProcessId]?.Value?.ToString();
string image = e.EventRecord.Properties[(int)NetworkConnectionEvent.Image]?.Value?.ToString();
string protocol = e.EventRecord.Properties[(int)NetworkConnectionEvent.Protocol]?.Value?.ToString();
string destinationIp = e.EventRecord.Properties[(int)NetworkConnectionEvent.DestinationIp]?.Value?.ToString();
string desinationPort = e.EventRecord.Properties[(int)NetworkConnectionEvent.DestinationPort]?.Value?.ToString();
string dstinationAddress = $"{protocol}://{destinationIp}:{desinationPort}";
logger.LogInformation($"> Detected the network connection: {dstinationAddress}");
logger.LogInformation(parent.DispatchServiceEvent("networkConnected", new string[] {
ruleName,
processId,
image,
dstinationAddress
}));
break;
}
case (int)EventType.RegistryEvent_1:
case (int)EventType.RegistryEvent_2:
case (int)EventType.RegistryEvent_3:
{
string ruleName = e.EventRecord.Properties[(int)RegistryEvent.RuleName]?.Value?.ToString();
string processId = e.EventRecord.Properties[(int)RegistryEvent.ProcessId]?.Value?.ToString();
string image = e.EventRecord.Properties[(int)RegistryEvent.Image]?.Value?.ToString();
string eventType = e.EventRecord.Properties[(int)RegistryEvent.EventType]?.Value?.ToString();
string targetObject = e.EventRecord.Properties[(int)RegistryEvent.TargetObject]?.Value?.ToString();
logger.LogInformation($"> Detected the registry modification: {targetObject}");
logger.LogInformation(parent.DispatchServiceEvent("registryModified", new string[] {
ruleName,
processId,
image,
eventType,
targetObject
}));
break;
}
default:
throw new ArgumentException("Not supported event type");
}
}
catch (Exception ex)
{
logger.LogInformation($"Failed to process the event bacause of {ex.Message}.");
}
}
else
{
logger.LogInformation("The event instance was null.");
}
}
private async Task ConnectToClamAv()
{
try {
// Create a client
clamAvClient = ClamAvClient.Create(new Uri(clamAvConenctionString));
// Send PING command to ClamAV
await clamAvClient.PingAsync().ConfigureAwait(false);
// Get ClamAV engine and virus database version
VersionResult result = await clamAvClient.GetVersionAsync().ConfigureAwait(false);
logger.LogInformation($"ClamAV version {result.ProgramVersion}, Virus database version {result.VirusDbVersion}");
}
catch (Exception ex)
{
logger.LogInformation($"Failed to read the address because of {ex.Message}. {clamAvConenctionString}");
clamAvClient = null;
}
}
private async Task ScanWithClamAv(string remotePath)
{
ScanResult res = await clamAvClient.ScanRemotePathAsync(remotePath).ConfigureAwait(false);
logger.LogInformation($"> Scan result: Infected={res.Infected}, VirusName={res.VirusName}");
logger.LogInformation(parent.DispatchServiceEvent("avScanResult", new string[] {
res.Infected.ToString(),
res.VirusName
}));
}
}
}

View File

@ -0,0 +1,160 @@
// HeartbeatClient.cs
// Namhyeon Go <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
using Grpc.Core;
using System.Threading.Tasks;
using System;
using System.Management;
using System.ServiceProcess;
using Grpc.Net.Client;
using Grpc.Net.Client.Web;
using System.Net.Http;
using Microsoft.Extensions.Logging;
namespace WelsonJS.Service
{
public class HeartbeatClient
{
private readonly HeartbeatService.HeartbeatServiceClient _client;
private ILogger logger;
private readonly GrpcChannel _channel;
private int HeartbeatInterval;
private ServiceMain parent;
private string clientId;
private string serverAddress;
public HeartbeatClient(ServiceBase _parent, ILogger _logger)
{
parent = (ServiceMain)_parent;
logger = _logger;
HeartbeatInterval = int.Parse(parent.ReadSettingsValue("HEARTBEAT_INTERVAL") ?? "2000");
try
{
serverAddress = parent.ReadSettingsValue("GRPC_HOST");
if (String.IsNullOrEmpty(serverAddress))
{
throw new Exception("The server address could not be empty.");
}
}
catch (Exception ex)
{
serverAddress = "http://localhost:50051";
logger.LogInformation($"Failed to read the address because of {ex.Message}. Set default: {serverAddress}");
}
var httpClientHandler = new HttpClientHandler();
var grpcWebHandler = new GrpcWebHandler(GrpcWebMode.GrpcWebText, httpClientHandler);
_channel = GrpcChannel.ForAddress(serverAddress, new GrpcChannelOptions
{
HttpHandler = grpcWebHandler,
Credentials = ChannelCredentials.Insecure
});
_client = new HeartbeatService.HeartbeatServiceClient(_channel);
clientId = GetSystemUUID().ToLower();
logger.LogInformation($"Use the client ID: {clientId}");
}
public async Task StartHeartbeatAsync()
{
while (true)
{
var call = _client.CheckHeartbeat();
try
{
var request = new HeartbeatRequest
{
IsAlive = true
};
await call.RequestStream.WriteAsync(request);
await call.RequestStream.CompleteAsync();
logger.LogInformation("Sent heartbeat");
await Task.Delay(HeartbeatInterval); // Wait for HeartbeatInterval
}
catch (Exception ex)
{
logger.LogInformation("Heartbeat request stream failed: " + ex.Message);
}
// 서버 응답을 수신하는 작업
try
{
while (await call.ResponseStream.MoveNext())
{
var response = call.ResponseStream.Current;
logger.LogInformation("Heartbeat response received: " + response.IsAlive);
}
}
catch (RpcException ex)
{
logger.LogInformation($"gRPC error: {ex.Status.Detail}");
}
catch (Exception ex)
{
logger.LogInformation($"Unexpected error: {ex.Message}");
}
finally
{
// 잠시 대기 후 재연결
await Task.Delay(TimeSpan.FromMilliseconds(HeartbeatInterval));
}
}
}
public async Task StartEventListenerAsync()
{
var eventRequest = new FetchEventsRequest
{
ClientId = clientId
};
while (true)
{
var eventCall = _client.FetchPendingEvents(eventRequest);
try
{
while (await eventCall.ResponseStream.MoveNext())
{
var response = eventCall.ResponseStream.Current;
logger.LogInformation($"Received event from server: {response.EventType} with args: {string.Join(", ", response.Args)}");
}
}
finally
{
await Task.Delay(TimeSpan.FromMilliseconds(HeartbeatInterval));
}
}
}
public async Task ShutdownAsync()
{
await _channel.ShutdownAsync();
}
private string GetSystemUUID()
{
try
{
using (var searcher = new ManagementObjectSearcher("SELECT UUID FROM Win32_ComputerSystemProduct"))
{
foreach (var mo in searcher.Get())
{
return mo["UUID"].ToString();
}
}
}
catch (Exception ex)
{
logger.LogInformation($"An error occurred while retrieving the system UUID: {ex.Message}");
}
return "UNKNOWN";
}
}
}

View File

@ -0,0 +1,62 @@
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);
}
}
}
}
}
}

View File

@ -0,0 +1,13 @@
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;
}
}
}

View File

@ -0,0 +1,24 @@
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
}
}
}

View File

@ -0,0 +1,13 @@
using System;
namespace WelsonJS.Service.Model
{
public class FileMatchResult
{
public string Id { get; set; }
public string FilePath { get; set; }
public ulong Offset { get; set; }
public string RuleName { get; set; }
public DateTime LastChecked { get; set; }
}
}

View File

@ -0,0 +1,24 @@
using System;
using System.Drawing;
namespace WelsonJS.Service
{
public class ScreenMatchResult
{
public string FileName { get; set; }
public int ScreenNumber { get; set; }
public IntPtr WindowHandle { get; set; }
public string WindowTitle { get; set; }
public string ProcessName { get; set; }
public Point WindowPosition { get; set; }
public Point Position { get; set; }
public string Text { get; set; }
public override string ToString()
{
return $"Template: {FileName}, Screen Number: {ScreenNumber}, Window Title: {WindowTitle}, " +
$"Process Name: {ProcessName}, Window Position: (x: {WindowPosition.X}, y: {WindowPosition.Y}), " +
$"Location: (x: {Position.X}, y: {Position.Y})";
}
}
}

View File

@ -0,0 +1,63 @@
using Microsoft.Extensions.Logging;
using System;
using System.IO;
using System.ServiceProcess;
using WelsonJS.Service.Logging;
namespace WelsonJS.Service
{
internal static class Program
{
private static ILogger logger;
/// <summary>
/// 해당 애플리케이션의 주 진입점입니다.
/// </summary>
///
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)
{
Console.WriteLine("WelsonJS Service Application (User Interactive Mode)");
Console.WriteLine("https://github.com/gnh1201/welsonjs");
Console.WriteLine();
Console.WriteLine("Service is running...");
ServiceMain svc = new ServiceMain(args, logger);
svc.TestStartupAndStop();
}
else
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new ServiceMain(args, logger)
};
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;
}
}
}

View File

@ -0,0 +1,61 @@
namespace WelsonJS.Service
{
partial class ProjectInstaller
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
/// </summary>
private void InitializeComponent()
{
this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();
this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller();
//
// serviceProcessInstaller1
//
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
this.serviceProcessInstaller1.Password = null;
this.serviceProcessInstaller1.Username = null;
//
// serviceInstaller1
//
this.serviceInstaller1.Description = "WelsonJS is the framework to build a Windows app on the Windows built-in JavaScri" +
"pt engine.";
this.serviceInstaller1.DisplayName = "WelsonJS.Service";
this.serviceInstaller1.ServiceName = "WelsonJS.Service";
this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic;
//
// ProjectInstaller
//
this.Installers.AddRange(new System.Configuration.Install.Installer[] {
this.serviceProcessInstaller1,
this.serviceInstaller1});
}
#endregion
private System.ServiceProcess.ServiceProcessInstaller serviceProcessInstaller1;
private System.ServiceProcess.ServiceInstaller serviceInstaller1;
}
}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
namespace WelsonJS.Service
{
[RunInstaller(true)]
public partial class ProjectInstaller : System.Configuration.Install.Installer
{
public ProjectInstaller()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,129 @@
<?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=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="serviceProcessInstaller1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="serviceInstaller1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>195, 17</value>
</metadata>
<metadata name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
</root>

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
// 이러한 특성 값을 변경하세요.
[assembly: AssemblyTitle("WelsonJS.Service")]
[assembly: AssemblyDescription("Windows Service for WelsonJS framework based applications")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Catswords")]
[assembly: AssemblyProduct("WelsonJS")]
[assembly: AssemblyCopyright("Catswords OSS, GPLv3 or Ms-RL")]
[assembly: AssemblyTrademark("WelsonJS")]
[assembly: AssemblyCulture("")]
// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요.
[assembly: ComVisible(false)]
// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
[assembly: Guid("09f295ee-5edb-4327-abbe-ddccdf5edd9e")]
// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.
//
// 주 버전
// 부 버전
// 빌드 번호
// 수정 버전
//
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
// 기본값으로 할 수 있습니다.
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.2.7.54")]
[assembly: AssemblyFileVersion("0.2.7.54")]

View File

@ -0,0 +1,27 @@
syntax = "proto3";
option csharp_namespace = "WelsonJS.Service";
package heartbeat;
service HeartbeatService {
rpc CheckHeartbeat (stream HeartbeatRequest) returns (stream HeartbeatResponse);
rpc FetchPendingEvents (FetchEventsRequest) returns (stream FetchEventsResponse);
}
message HeartbeatRequest {
bool is_alive = 1;
}
message HeartbeatResponse {
bool is_alive = 1;
}
message FetchEventsRequest {
string client_id = 1;
}
message FetchEventsResponse {
string event_type = 1;
repeated string args = 2;
}

View File

@ -0,0 +1,927 @@
// ScreenMatching.cs
// https://github.com/gnh1201/welsonjs
// https://catswords-oss.rdbl.io/5719744820/8803957194
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.IO.Hashing;
using System.Runtime.InteropServices;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Linq;
using Tesseract;
using WelsonJS.Service;
using Microsoft.Extensions.Logging;
public class ScreenMatch
{
// User32.dll API 함수 선언
[DllImport("user32.dll")]
private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll")]
private static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern int GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
private static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("user32.dll")]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll")]
private static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("gdi32.dll")]
private static extern bool BitBlt(IntPtr hDestDC, int x, int y, int nWidth, int nHeight, IntPtr hSrcDC, int xSrc, int ySrc, int dwRop);
[DllImport("user32.dll", SetLastError = true)]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll")]
private static extern bool EnumDisplaySettings(string lpszDeviceName, int iModeNum, ref DEVMODE lpDevMode);
// https://stackoverflow.com/questions/60872044/how-to-get-scaling-factor-for-each-monitor-e-g-1-1-25-1-5
[StructLayout(LayoutKind.Sequential)]
private struct DEVMODE
{
private const int CCHDEVICENAME = 0x20;
private const int CCHFORMNAME = 0x20;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public int dmPositionX;
public int dmPositionY;
public ScreenOrientation dmDisplayOrientation;
public int dmDisplayFixedOutput;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
public string dmFormName;
public short dmLogPixels;
public int dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmDisplayFlags;
public int dmDisplayFrequency;
public int dmICMMethod;
public int dmICMIntent;
public int dmMediaType;
public int dmDitherType;
public int dmReserved1;
public int dmReserved2;
public int dmPanningWidth;
public int dmPanningHeight;
}
private const int SRCCOPY = 0x00CC0020;
// 델리게이트 선언
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
// RECT 구조체 선언
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
private ServiceMain parent;
private ILogger logger;
private List<Bitmap> templateImages;
private string templateDirectoryPath;
private string outputDirectoryPath;
private int templateCurrentIndex = 0;
private double threshold = 0.3;
private string mode;
private bool busy;
private List<string> _params = new List<string>();
private bool isSearchFromEnd = false;
private bool isSaveToFile = false;
private Size sampleSize;
private int sampleAdjustX;
private int sampleAdjustY;
private List<string> sampleAny;
private List<string> sampleClipboard;
private List<string> sampleOcr;
private List<string> sampleNodup;
private Size sampleNodupSize;
private Queue<Bitmap> outdatedSamples;
private string tesseractDataPath;
private string tesseractLanguage;
private void SetBusy(bool busy)
{
this.busy = busy;
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");
outputDirectoryPath = Path.Combine(workingDirectory, "app/assets/img/_captured");
templateImages = new List<Bitmap>();
// Initialize variables for sampling process
sampleSize = new Size
{
Width = 128,
Height = 128
};
sampleAdjustX = 0;
sampleAdjustY = 0;
sampleAny = new List<string>();
sampleClipboard = new List<string>();
sampleOcr = new List<string>();
sampleNodup = new List<string>();
sampleNodupSize = new Size
{
Width = 180,
Height = 60
};
outdatedSamples = new Queue<Bitmap>();
// Read values from configration file
string screen_time_mode;
string screen_time_params;
try
{
screen_time_mode = parent.ReadSettingsValue("SCREEN_TIME_MODE");
screen_time_params = parent.ReadSettingsValue("SCREEN_TIME_PARAMS");
}
catch (Exception ex)
{
screen_time_mode = null;
screen_time_params = null;
logger.LogInformation($"Failed to read from configration file: {ex.Message}");
}
if (!String.IsNullOrEmpty(screen_time_params))
{
var screen_time_configs = screen_time_params
.Split(',')
.Select(pair => pair.Split('='))
.ToDictionary(
parts => parts[0],
parts => parts.Length > 1 ? parts[1] : parts[0]
);
var config_keys = new string[]
{
"process_name",
"sample_width",
"sample_height",
"sample_adjust_x",
"sample_adjust_y",
"sample_any",
"sample_nodup",
"backward",
"save",
"sample_clipboard",
"sample_ocr"
};
foreach (var config_key in config_keys)
{
string config_value;
screen_time_configs.TryGetValue(config_key, out config_value);
if (config_value != null)
{
switch (config_key)
{
case "backward":
{
isSearchFromEnd = true;
logger.LogInformation("Use the backward search when screen time");
break;
}
case "save":
{
isSaveToFile = true;
logger.LogInformation("Will be save an image file when capture the screens");
break;
}
case "threshold":
{
double.TryParse(config_value, out double t);
threshold = t;
break;
}
case "sample_clipboard":
{
sampleClipboard = new List<string>(config_value.Split(':'));
break;
}
case "sample_ocr":
{
tesseractDataPath = Path.Combine(workingDirectory, "app/assets/tessdata_best");
tesseractLanguage = "eng";
sampleOcr = new List<string>(config_value.Split(':'));
break;
}
case "sample_width":
{
int.TryParse(config_value, out int w);
sampleSize.Width = w;
break;
}
case "sample_height":
{
int.TryParse(config_value, out int h);
sampleSize.Height = h;
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":
{
int.TryParse(config_value, out sampleAdjustX);
break;
}
case "sample_adjust_y":
{
int.TryParse(config_value, out sampleAdjustY);
break;
}
case "sample_any":
{
sampleAny = new List<string>(config_value.Split(':'));
break;
}
case "sample_nodup":
{
sampleNodup = new List<string>(config_value.Split(':'));
break;
}
}
}
}
}
SetMode(screen_time_mode);
LoadTemplateImages();
}
public void SetMode(string mode)
{
if (!String.IsNullOrEmpty(mode))
{
this.mode = mode;
}
else
{
this.mode = "screen";
}
}
public void SetThreshold(double threshold)
{
this.threshold = threshold;
}
public void LoadTemplateImages()
{
string[] files;
try
{
files = Directory.GetFiles(templateDirectoryPath, "*.png");
}
catch (Exception ex)
{
files = new string[]{};
logger.LogInformation($"Failed to read the directory structure: {ex.Message}");
}
foreach (var file in files)
{
string filename = Path.GetFileName(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
};
if (!filename.StartsWith("no_"))
{
if (filename.StartsWith("binary_"))
{
templateImages.Add(ImageQuantize(bitmap));
}
else
{
templateImages.Add(bitmap);
}
}
}
}
// 캡쳐 및 템플릿 매칭 진행
public List<ScreenMatchResult> CaptureAndMatch()
{
List<ScreenMatchResult> results = new List<ScreenMatchResult>();
if (busy)
{
throw new Exception("Waiting done a previous job...");
}
if (templateImages.Count > 0)
{
SetBusy(true);
switch (mode)
{
case "screen": // 화면 기준
results = CaptureAndMatchAllScreens();
SetBusy(false);
break;
case "window": // 윈도우 핸들 기준
results = CaptureAndMatchAllWindows();
SetBusy(false);
break;
default:
SetBusy(false);
throw new Exception($"Unknown capture mode {mode}");
}
}
return results;
}
// 화면을 기준으로 찾기
public List<ScreenMatchResult> CaptureAndMatchAllScreens()
{
var results = new List<ScreenMatchResult>();
for (int i = 0; i < Screen.AllScreens.Length; i++)
{
Screen screen = Screen.AllScreens[i];
Bitmap mainImage = CaptureScreen(screen);
Bitmap templateImage = templateImages[templateCurrentIndex];
string templateName = templateImage.Tag as string;
TemplateInfo nextTemplateInfo = parent.GetNextTemplateInfo();
Size templateSize = new Size
{
Width = templateImage.Width,
Height = templateImage.Height
};
logger.LogInformation($"Trying match the template {templateName} on the screen {i}...");
if (!String.IsNullOrEmpty(nextTemplateInfo.FileName) && templateName != nextTemplateInfo.FileName)
{
logger.LogInformation($"Ignored the template {templateName}");
break;
}
Bitmap out_mainImage;
string out_filename;
if (templateName.StartsWith("binary_"))
{
out_mainImage = ImageQuantize((Bitmap)mainImage.Clone());
out_filename = $"{DateTime.Now:yyyy-MM-dd hh mm ss} binary.png";
}
else
{
out_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());
}
foreach (Point matchPosition in matchPositions)
{
try
{
string text = sampleAny.Contains(templateName) ?
InspectSample((Bitmap)mainImage.Clone(), matchPosition, templateSize, templateName, sampleSize) : string.Empty;
results.Add(new ScreenMatchResult
{
FileName = templateName,
ScreenNumber = i,
Position = matchPosition,
Text = text
});
break; // Only one
}
catch (Exception ex)
{
logger.LogInformation($"Ignore the match. {ex.Message}");
}
}
}
if (results.Count > 0)
{
logger.LogInformation("Match found");
}
else
{
logger.LogInformation($"No match found");
}
templateCurrentIndex = ++templateCurrentIndex % templateImages.Count;
return results;
}
public Bitmap CropBitmap(Bitmap bitmap, Point matchPosition, Size templateSize, Size sampleSize, int dx = 0, int dy = 0)
{
// Adjust coordinates to the center
int x = matchPosition.X + (templateSize.Width / 2);
int y = matchPosition.Y + (templateSize.Height / 2);
// Set range of crop image
int cropX = Math.Max((x - sampleSize.Width / 2) + dx, 0);
int cropY = Math.Max((y - sampleSize.Height / 2) + dy, 0);
int cropWidth = Math.Min(sampleSize.Width, bitmap.Width - cropX);
int cropHeight = Math.Min(sampleSize.Height, bitmap.Height - cropY);
Rectangle cropArea = new Rectangle(cropX, cropY, cropWidth, cropHeight);
// Crop image
return bitmap.Clone(cropArea, bitmap.PixelFormat);
}
public string InspectSample(Bitmap bitmap, Point matchPosition, Size templateSize, string templateName, Size sampleSize)
{
if (bitmap == null)
{
throw new ArgumentNullException(nameof(bitmap), "Bitmap cannot be null.");
}
if (matchPosition == null || matchPosition == Point.Empty)
{
throw new ArgumentException("matchPosition cannot be empty.");
}
// initialize the text
string text = "";
// Crop image
Bitmap croppedBitmap = CropBitmap(bitmap, matchPosition, templateSize, sampleSize, sampleAdjustX, sampleAdjustY);
// Save to the outdated samples
if (sampleNodup.Contains(templateName))
{
Bitmap croppedNodupBitmap = CropBitmap(bitmap, matchPosition, templateSize, sampleNodupSize);
uint bitmapCrc32 = ComputeBitmapCrc32(croppedNodupBitmap);
croppedNodupBitmap.Tag = new SampleInfo(templateName, bitmapCrc32);
bool bitmapExists = outdatedSamples.Any(x => ((SampleInfo)x.Tag).Crc32 == bitmapCrc32);
if (bitmapExists)
{
throw new InvalidOperationException($"This may be a duplicate request. {templateName}");
}
else
{
outdatedSamples.Enqueue(croppedNodupBitmap);
logger.LogInformation($"Added to the image queue. {templateName}");
}
}
// if use Clipboard
if (sampleClipboard.Contains(templateName))
{
logger.LogInformation($"Trying to use the clipboard... {templateName}");
Thread th = new Thread(new ThreadStart(() =>
{
try
{
Clipboard.SetImage((Bitmap)croppedBitmap.Clone());
logger.LogInformation($"Copied the image to Clipboard");
}
catch (Exception ex)
{
logger.LogInformation($"Failed to copy to the clipboard: {ex.Message}");
}
}));
th.SetApartmentState(ApartmentState.STA);
th.Start();
}
// if use OCR
if (sampleOcr.Contains(templateName))
{
try
{
using (var engine = new TesseractEngine(tesseractDataPath, tesseractLanguage, EngineMode.Default))
{
using (var page = engine.Process(croppedBitmap))
{
text = page.GetText();
logger.LogInformation($"Mean confidence: {page.GetMeanConfidence()}");
logger.LogInformation($"Text (GetText): {text}");
}
}
}
catch (Exception ex)
{
logger.LogInformation($"Failed to OCR: {ex.Message}");
}
}
return text;
}
public Bitmap CaptureScreen(Screen screen)
{
Rectangle screenSize = screen.Bounds;
decimal scalingFactor = GetScreenScalingFactor(screen);
int adjustedWidth = (int)(screenSize.Width * scalingFactor);
int adjustedHeight = (int)(screenSize.Height * scalingFactor);
Bitmap bitmap = new Bitmap(adjustedWidth, adjustedHeight);
using (Graphics bitmapGraphics = Graphics.FromImage(bitmap))
{
bitmapGraphics.CopyFromScreen(screenSize.Left, screenSize.Top, 0, 0, new Size(adjustedWidth, adjustedHeight));
}
return bitmap;
}
// 윈도우 핸들을 기준으로 찾기
public List<ScreenMatchResult> CaptureAndMatchAllWindows()
{
var results = new List<ScreenMatchResult>();
// 모든 윈도우 핸들을 열거
EnumWindows((hWnd, lParam) =>
{
if (IsWindowVisible(hWnd))
{
try
{
string windowTitle = GetWindowTitle(hWnd);
string processName = GetProcessName(hWnd);
GetWindowRect(hWnd, out RECT windowRect);
Point windowPosition = new Point(windowRect.Left, windowRect.Top);
Bitmap windowImage = CaptureWindow(hWnd);
if (windowImage != null)
{
Bitmap image = templateImages[templateCurrentIndex];
string templateName = image.Tag as string;
Size templateSize = new Size
{
Width = image.Width,
Height = image.Height
};
List<Point> matchPositions = FindTemplate(windowImage, image);
matchPositions.ForEach((matchPosition) =>
{
try
{
string text = sampleAny.Contains(templateName) ?
InspectSample((Bitmap)windowImage.Clone(), matchPosition, templateSize, templateName, sampleSize) : string.Empty;
results.Add(new ScreenMatchResult
{
FileName = templateName,
WindowHandle = hWnd,
WindowTitle = windowTitle,
ProcessName = processName,
WindowPosition = windowPosition,
Position = matchPosition,
Text = text
});
}
catch (Exception ex)
{
logger.LogInformation($"Ignore the match. {ex.Message}");
}
});
}
}
catch (Exception ex) {
logger.LogInformation($"Error {ex.Message}");
}
}
return true;
}, IntPtr.Zero);
templateCurrentIndex = ++templateCurrentIndex % templateImages.Count;
return results;
}
public string GetWindowTitle(IntPtr hWnd)
{
int length = GetWindowTextLength(hWnd);
StringBuilder sb = new StringBuilder(length + 1);
GetWindowText(hWnd, sb, sb.Capacity);
return sb.ToString();
}
public string GetProcessName(IntPtr hWnd)
{
uint processId;
GetWindowThreadProcessId(hWnd, out processId);
Process process = Process.GetProcessById((int)processId);
return process.ProcessName;
}
public Bitmap CaptureWindow(IntPtr hWnd)
{
GetWindowRect(hWnd, out RECT rect);
int width = rect.Right - rect.Left;
int height = rect.Bottom - rect.Top;
if (width <= 0 || height <= 0)
return null;
Bitmap bitmap = new Bitmap(width, height);
Graphics graphics = Graphics.FromImage(bitmap);
IntPtr hDC = graphics.GetHdc();
IntPtr windowDC = GetDC(hWnd);
bool success = BitBlt(hDC, 0, 0, width, height, windowDC, 0, 0, SRCCOPY);
ReleaseDC(hWnd, windowDC);
graphics.ReleaseHdc(hDC);
return success ? bitmap : null;
}
public List<Point> FindTemplate(Bitmap mainImage, Bitmap templateImage)
{
var matches = new List<Point>();
int mainWidth = mainImage.Width;
int mainHeight = mainImage.Height;
int templateWidth = templateImage.Width;
int templateHeight = templateImage.Height;
int startX = isSearchFromEnd ? mainWidth - templateWidth : 0;
int endX = isSearchFromEnd ? -1 : mainWidth - templateWidth + 1;
int stepX = isSearchFromEnd ? -1 : 1;
int startY = isSearchFromEnd ? mainHeight - templateHeight : 0;
int endY = isSearchFromEnd ? -1 : mainHeight - templateHeight + 1;
int stepY = isSearchFromEnd ? -1 : 1;
for (int x = startX; x != endX; x += stepX)
{
for (int y = startY; y != endY; y += stepY)
{
if (IsTemplateMatch(mainImage, templateImage, x, y, threshold))
{
matches.Add(new Point(x, y));
}
}
}
return matches;
}
private bool IsTemplateMatch(Bitmap mainImage, Bitmap templateImage, int offsetX, int offsetY, double threshold)
{
int templateWidth = templateImage.Width;
int templateHeight = templateImage.Height;
int totalPixels = templateWidth * templateHeight;
int requiredMatches = (int)(totalPixels * threshold);
// When the square root of the canvas size of the image to be matched is less than 10, a complete match is applied.
if (Math.Sqrt(templateWidth * templateHeight) < 10.0)
{
for (int y = 0; y < templateHeight; y++)
{
for (int x = 0; x < templateWidth; x++)
{
if (mainImage.GetPixel(x + offsetX, y + offsetY) != templateImage.GetPixel(x, y))
{
return false;
}
}
}
return true;
}
// Otherwise, randomness is used.
int matchedCount = 0;
Random rand = new Random();
while (matchedCount < requiredMatches)
{
int x = rand.Next(templateWidth);
int y = rand.Next(templateHeight);
if (mainImage.GetPixel(x + offsetX, y + offsetY) != templateImage.GetPixel(x, y))
{
return false;
}
matchedCount++;
}
return true;
}
private Bitmap ImageQuantize(Bitmap image, int levels = 4)
{
Bitmap quantizedImage = new Bitmap(image.Width, image.Height);
if (image.Tag != null)
{
quantizedImage.Tag = image.Tag;
}
int step = 255 / (levels - 1); // step by step..... ooh baby...(?)
for (int y = 0; y < image.Height; y++)
{
for (int x = 0; x < image.Width; x++)
{
// Convert the pixel to grayscale
Color pixelColor = image.GetPixel(x, y);
byte grayValue = (byte)((pixelColor.R + pixelColor.G + pixelColor.B) / 3);
// Convert the grayscale value to the quantize value
byte quantizedValue = (byte)((grayValue / step) * step);
// Renew the colors
Color quantizedColor = Color.FromArgb(quantizedValue, quantizedValue, quantizedValue);
quantizedImage.SetPixel(x, y, quantizedColor);
}
}
return quantizedImage;
}
private uint ComputeBitmapCrc32(Bitmap bitmap)
{
using (MemoryStream ms = new MemoryStream())
{
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
byte[] bitmapBytes = ms.ToArray();
Crc32 crc32 = new Crc32();
crc32.Append(bitmapBytes);
return BitConverter.ToUInt32(crc32.GetCurrentHash(), 0);
}
}
}

View File

@ -0,0 +1,40 @@
namespace WelsonJS.Service
{
partial class ServiceMain
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
/// </summary>
private void InitializeComponent()
{
//
// ServiceMain
//
this.ServiceName = "ServiceMain";
}
#endregion
}
}

View File

@ -0,0 +1,496 @@
/*
* WelsonJS.Service
*
* filename:
* ServiceMain.cs
*
* description:
* WelsonJS - Build a Windows app on the Windows built-in JavaScript engine
*
* website:
* - https://github.com/gnh1201/welsonjs
* - https://catswords.social/@catswords_oss
* - https://teams.live.com/l/community/FEACHncAhq8ldnojAI
*
* author:
* Namhyeon Go <abuse@catswords.net>
*
* license:
* GPLv3 or MS-RL(Microsoft Reciprocal License)
*
* references:
* - https://learn.microsoft.com/en-us/dotnet/framework/windows-services/how-to-debug-windows-service-applications
* - https://stackoverflow.com/questions/6490979/how-to-pass-parameters-to-windows-service
* - https://stackoverflow.com/questions/42812333/pass-an-argument-to-a-windows-service-at-automatic-startup
* - https://learn.microsoft.com/ko-kr/windows/win32/api/winuser/nf-winuser-getsystemmetrics
*/
using System;
using System.ServiceProcess;
using System.Timers;
using System.Runtime.InteropServices;
using MSScriptControl;
using System.IO;
using System.Collections.Generic;
using WelsonJS.TinyINIController;
using System.Collections;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
namespace WelsonJS.Service
{
public partial class ServiceMain : ServiceBase
{
private readonly static string applicationName = "WelsonJS";
private static List<Timer> timers;
private ILogger logger;
private string workingDirectory;
private string scriptName;
private string scriptFilePath;
private string scriptText;
private ScriptControl scriptControl;
private string[] args;
private bool disabledHeartbeat = false;
private bool disabledScreenTime = false;
private bool disabledFileMonitor = false;
private ScreenMatch screenMatcher;
private FileEventMonitor fileEventMonitor;
private IniFile settingsFileHandler;
private UserVariables userVariablesHandler;
[DllImport("user32.dll")]
private static extern int GetSystemMetrics(int nIndex);
private static int SM_REMOTESESSION = 0x1000;
public ServiceMain(string[] _args, ILogger _logger)
{
InitializeComponent();
// set arguments and logger
args = _args;
logger = _logger;
// mapping arguments to each variables
var arguments = ParseArguments(this.args);
foreach (KeyValuePair<string, string> entry in arguments)
{
switch (entry.Key)
{
case "working-directory":
workingDirectory = entry.Value;
break;
case "script-name":
scriptName = entry.Value;
break;
case "disable-heartbeat":
disabledHeartbeat = true;
break;
case "disable-screen-time":
disabledScreenTime = true;
break;
case "disable-file-monitor":
disabledFileMonitor = true;
break;
}
}
// load the user variables
userVariablesHandler = new UserVariables(this);
userVariablesHandler.Load();
// set timers
timers = new List<Timer>();
// set working directory
if (string.IsNullOrEmpty(workingDirectory))
{
workingDirectory = Path.Combine(Path.GetTempPath(), applicationName);
logger.LogInformation("Working directory not provided. Using default value: " + workingDirectory);
if (!Directory.Exists(workingDirectory))
{
Directory.CreateDirectory(workingDirectory);
logger.LogInformation("Directory created: " + workingDirectory);
}
}
Directory.SetCurrentDirectory(workingDirectory);
// read settings.ini
string settingsFilePath = Path.Combine(workingDirectory, "settings.ini");
if (File.Exists(settingsFilePath))
{
try
{
settingsFileHandler = new IniFile(settingsFilePath);
}
catch (Exception ex)
{
logger.LogWarning(ex.Message);
}
}
else
{
logger.LogInformation($"Configuration file not found: {settingsFilePath}");
}
// read configrations from settings.ini
if (settingsFileHandler != null)
{
string[] configNames = new string[]
{
"DISABLE_HEARTBEAT",
"DISABLE_SCREEN_TIME",
"DISABLE_FILE_MONITOR"
};
foreach (string configName in configNames)
{
try
{
if ("true" == ReadSettingsValue(configName))
{
switch (configName)
{
case "DISABLE_HEARTBEAT":
disabledHeartbeat = true;
break;
case "DISABLE_SCREEN_TIME":
disabledScreenTime = true;
break;
case "DISABLE_FILE_MONITOR":
disabledFileMonitor = true;
break;
default:
break;
}
}
}
catch (Exception ex)
{
logger.LogInformation($"{configName} is ignored: {ex.Message}");
}
}
}
// set script name
if (string.IsNullOrEmpty(scriptName))
{
scriptName = "defaultService";
logger.LogInformation($"Script name not provided. Using default value: {scriptName}");
}
// set path of the script
scriptFilePath = Path.Combine(workingDirectory, "app.js");
// start the heartbeat
if (!disabledHeartbeat)
{
HeartbeatClient heartbeatClient = new HeartbeatClient(this, logger);
Task.Run(heartbeatClient.StartHeartbeatAsync);
Task.Run(heartbeatClient.StartEventListenerAsync);
}
// set default timer
Timer defaultTimer = new Timer
{
Interval = 60000 // 1 minute
};
defaultTimer.Elapsed += OnElapsedTime;
timers.Add(defaultTimer);
// check this session is the user interactive mode
if (Environment.UserInteractive) {
OnUserInteractiveEnvironment();
}
else
{
logger.LogInformation("Disabled the User Interactive Mode. (e.g., OnScreenTime)");
}
logger.LogInformation(applicationName + " Service Loaded");
}
public string ReadSettingsValue(string key, string defaultValue = null)
{
if (settingsFileHandler != null)
{
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()
{
this.OnStart(this.args);
Console.ReadLine();
this.OnStop();
}
protected override void OnStart(string[] args)
{
base.OnStart(args);
// Check exists the entry script file
if (File.Exists(scriptFilePath))
{
logger.LogInformation($"Script file found: {scriptFilePath}");
try
{
// load the script
scriptText = File.ReadAllText(scriptFilePath);
scriptControl = new ScriptControl
{
Language = "JScript",
AllowUI = false
};
scriptControl.Reset();
scriptControl.AddCode(scriptText);
// make the start arguments
string[] startArguments;
string[] _args;
if (Environment.UserInteractive)
{
_args = new string[]
{
$"--env-file={userVariablesHandler.GetEnvFilePath()}",
"--user-interactive"
};
}
else
{
_args = new string[]
{
$"--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
logger.LogInformation(DispatchServiceEvent("start", startArguments));
}
catch (Exception ex)
{
logger.LogInformation($"Failed to start because of {ex.Message}");
}
}
else
{
logger.LogInformation($"Script file not found: {scriptFilePath}");
}
// Trace a Sysmon file events (If Sysinternals Sysmon installed)
if (!disabledFileMonitor)
{
fileEventMonitor = new FileEventMonitor(this, workingDirectory, logger);
fileEventMonitor.Start();
logger.LogInformation("File Event Monitor Started");
}
else
{
logger.LogInformation("File Event Monitor is Disabled");
}
// Start all the registered timers
timers.ForEach(timer => timer?.Start());
logger.LogInformation(applicationName + " Service Started");
}
protected override void OnStop()
{
// stop timers
timers.ForEach(timer => timer?.Stop());
// stop the File Event Monitor
fileEventMonitor?.Stop();
// dispatch stop callback
try
{
logger.LogInformation(DispatchServiceEvent("stop"));
scriptControl?.Reset();
}
catch (Exception ex)
{
logger.LogInformation("Exception when stop: " + ex.Message);
}
scriptControl = null;
logger.LogInformation(applicationName + " Service Stopped");
}
private void OnUserInteractiveEnvironment()
{
// check is it a remote desktop session
if (GetSystemMetrics(SM_REMOTESESSION) > 0)
{
disabledScreenTime = true;
logger.LogInformation("This application may not work correctly in a remote desktop session");
}
// set screen timer
if (!disabledScreenTime)
{
screenMatcher = new ScreenMatch(this, workingDirectory, logger);
Timer screenTimer = new Timer
{
Interval = 1000 // 1 seconds
};
screenTimer.Elapsed += OnScreenTime;
timers.Add(screenTimer);
logger.LogInformation("Screen Time Event Enabled");
}
else
{
disabledScreenTime = true;
logger.LogInformation("Screen Time Event Disabled");
}
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
try
{
logger.LogInformation(DispatchServiceEvent("elapsedTime"));
}
catch (Exception ex)
{
logger.LogInformation("Exception when elapsed time: " + ex.Message);
}
}
private void OnScreenTime(object source, ElapsedEventArgs e)
{
try
{
List<ScreenMatchResult> matchedResults = screenMatcher.CaptureAndMatch();
matchedResults.ForEach(result =>
{
logger.LogInformation(DispatchServiceEvent("screenTemplateMatched", new string[]
{
result.FileName,
result.ScreenNumber.ToString(),
result.Position.X.ToString(),
result.Position.Y.ToString()
}));
});
}
catch (Exception ex)
{
logger.LogInformation($"Waiting a next screen time... {ex.Message}");
}
}
private string InvokeScriptMethod(string methodName, string scriptName, string eventType, string[] args)
{
if (scriptControl != null)
{
object[] parameters = new object[] {
scriptName,
eventType,
new ArrayList(args),
args.Length
};
//scriptControl.AddObject("extern_arguments", new ArrayList(args), true);
return scriptControl.Run(methodName, parameters)?.ToString() ?? "void";
}
else
{
logger.LogInformation("InvokeScriptMethod Ignored: " + methodName);
}
return "void";
}
private Dictionary<string, string> ParseArguments(string[] args)
{
var arguments = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (string arg in args)
{
if (arg.StartsWith("--"))
{
var index = arg.IndexOf('=');
if (index > 2)
{
var key = arg.Substring(2, index - 2);
var value = arg.Substring(index + 1).Trim('"');
arguments[key] = value;
}
else
{
var key = arg.Substring(2, index - 2);
arguments[key] = "";
}
}
}
return arguments;
}
public ScreenMatch.TemplateInfo GetNextTemplateInfo()
{
string templateName = string.Empty;
int index = 0;
try
{
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)
{
logger.LogInformation($"Use all templates because of {ex.Message}");
}
return new ScreenMatch.TemplateInfo(templateName, index);
}
public string DispatchServiceEvent(string eventType, string[] args = null)
{
if (args == null)
{
return InvokeScriptMethod("dispatchServiceEvent", scriptName, eventType, new string[] { });
}
else
{
return InvokeScriptMethod("dispatchServiceEvent", scriptName, eventType, args);
}
}
}
}

View File

@ -0,0 +1,82 @@
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;
}
}
}

View File

@ -0,0 +1,300 @@
<?xml version="1.0" encoding="utf-8"?>
<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="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{09F295EE-5EDB-4327-ABBE-DDCCDF5EDD9E}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>WelsonJS.Service</RootNamespace>
<AssemblyName>WelsonJS.Service</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<PublishUrl>게시\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>favicon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<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>
</Reference>
<Reference Include="Google.Protobuf, Version=3.28.2.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
<HintPath>..\packages\Google.Protobuf.3.28.2\lib\net45\Google.Protobuf.dll</HintPath>
</Reference>
<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>
</Reference>
<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>
</Reference>
<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>
</Reference>
<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>
</Reference>
<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>
</Reference>
<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>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Extensions.Configuration, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.Configuration.8.0.0\lib\net462\Microsoft.Extensions.Configuration.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Configuration.Abstractions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.Configuration.Abstractions.8.0.0\lib\net462\Microsoft.Extensions.Configuration.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Configuration.Binder, Version=8.0.0.2, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.Configuration.Binder.8.0.2\lib\net462\Microsoft.Extensions.Configuration.Binder.dll</HintPath>
</Reference>
<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 Include="System" />
<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>
</Reference>
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Configuration.Install" />
<Reference Include="System.Data" />
<Reference Include="System.Diagnostics.DiagnosticSource, Version=8.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Diagnostics.DiagnosticSource.8.0.1\lib\net462\System.Diagnostics.DiagnosticSource.dll</HintPath>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.IO.Hashing, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.Hashing.8.0.0\lib\net462\System.IO.Hashing.dll</HintPath>
</Reference>
<Reference Include="System.Management" />
<Reference Include="System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.WinHttpHandler, Version=8.0.0.2, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Net.Http.WinHttpHandler.8.0.2\lib\net462\System.Net.Http.WinHttpHandler.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<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>
</Reference>
<Reference Include="System.Runtime" />
<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>
</Reference>
<Reference Include="System.ServiceProcess" />
<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>
</Reference>
<Reference Include="System.Text.Json, Version=8.0.0.5, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Text.Json.8.0.5\lib\net462\System.Text.Json.dll</HintPath>
</Reference>
<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>
</Reference>
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="System.Web" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="Tesseract, Version=5.2.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Tesseract.5.2.0\lib\net48\Tesseract.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="FileEventMonitor.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="ServiceMain.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="ServiceMain.Designer.cs">
<DependentUpon>ServiceMain.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="ProjectInstaller.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="ProjectInstaller.Designer.cs">
<DependentUpon>ProjectInstaller.cs</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ScreenMatch.cs" />
<Compile Include="Model\ScreenMatchResult.cs" />
<Compile Include="UserVariables.cs" />
</ItemGroup>
<ItemGroup>
<COMReference Include="MSScriptControl">
<Guid>{0E59F1D2-1FBE-11D0-8FF2-00A0D10038BC}</Guid>
<VersionMajor>1</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
<Private>True</Private>
</COMReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="ProjectInstaller.resx">
<DependentUpon>ProjectInstaller.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WelsonJS.Toolkit\WelsonJS.Toolkit.csproj">
<Project>{d6007282-b4f7-4694-ac67-bb838d91b77a}</Project>
<Name>WelsonJS.Toolkit</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.8">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.8%28x86 및 x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<Content Include="favicon.ico" />
</ItemGroup>
<ItemGroup>
<Protobuf Include="Protos\heartbeat.proto" GrpcServices="Client" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>이 프로젝트는 이 컴퓨터에 없는 NuGet 패키지를 참조합니다. 해당 패키지를 다운로드하려면 NuGet 패키지 복원을 사용하십시오. 자세한 내용은 http://go.microsoft.com/fwlink/?LinkID=322105를 참조하십시오. 누락된 파일은 {0}입니다.</ErrorText>
</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\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>
<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\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>

View File

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" /></startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<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" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.1" newVersion="8.0.0.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.WinHttpHandler" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.2" newVersion="8.0.0.2" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="DeviceId" publicKeyToken="f755c371b5c59c52" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.7.0.0" newVersion="6.7.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Google.Protobuf" publicKeyToken="a7d26565bac4d604" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.27.3.0" newVersion="3.27.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Grpc.Core" publicKeyToken="d754f35622e28bad" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Grpc.Core.Api" publicKeyToken="d754f35622e28bad" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Grpc.Net.Client" publicKeyToken="d754f35622e28bad" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Grpc.Net.Client.Web" publicKeyToken="d754f35622e28bad" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Grpc.Net.Common" publicKeyToken="d754f35622e28bad" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<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" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="RestSharp" publicKeyToken="598062e77f915f75" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-112.0.0.0" newVersion="112.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.4.0" newVersion="4.1.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Encodings.Web" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Json" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.5" newVersion="8.0.0.5" />
</dependentAssembly>
<dependentAssembly>
<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" />
</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>
</runtime>
</configuration>

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ClamAV.Net" version="0.1.166" targetFramework="net48" />
<package id="Google.Protobuf" version="3.28.2" 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.Api" version="2.66.0" targetFramework="net48" />
<package id="Grpc.Net.Client" version="2.66.0" targetFramework="net48" />
<package id="Grpc.Net.Client.Web" version="2.66.0" targetFramework="net48" />
<package id="Grpc.Net.Common" version="2.66.0" targetFramework="net48" />
<package id="Grpc.Tools" version="2.67.0" targetFramework="net48" developmentDependency="true" />
<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.Configuration.Abstractions" version="8.0.0" targetFramework="net48" />
<package id="Microsoft.Extensions.Configuration.Binder" version="8.0.2" 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.Diagnostics.DiagnosticSource" version="8.0.1" targetFramework="net48" />
<package id="System.IO.Hashing" version="8.0.0" targetFramework="net48" />
<package id="System.Memory" version="4.5.5" targetFramework="net48" />
<package id="System.Net.Http.WinHttpHandler" version="8.0.2" 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.Text.Encodings.Web" version="8.0.0" targetFramework="net48" />
<package id="System.Text.Json" version="8.0.5" 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="Tesseract" version="5.2.0" targetFramework="net48" />
</packages>

View File

@ -1,10 +1,14 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31515.178
# Visual Studio Version 17
VisualStudioVersion = 17.8.34322.80
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WelsonJS.Toolkit", "WelsonJS.Toolkit\WelsonJS.Toolkit.csproj", "{D6007282-B4F7-4694-AC67-BB838D91B77A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WelsonJS.Service", "WelsonJS.Service\WelsonJS.Service.csproj", "{09F295EE-5EDB-4327-ABBE-DDCCDF5EDD9E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WelsonJS.Launcher", "WelsonJS.Launcher\WelsonJS.Launcher.csproj", "{4074D413-195C-45E9-9E63-0D07914187B8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -15,10 +19,28 @@ Global
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D6007282-B4F7-4694-AC67-BB838D91B77A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D6007282-B4F7-4694-AC67-BB838D91B77A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D6007282-B4F7-4694-AC67-BB838D91B77A}.Debug|x86.ActiveCfg = Debug|Any CPU
{D6007282-B4F7-4694-AC67-BB838D91B77A}.Debug|x86.ActiveCfg = Debug|x86
{D6007282-B4F7-4694-AC67-BB838D91B77A}.Debug|x86.Build.0 = Debug|x86
{D6007282-B4F7-4694-AC67-BB838D91B77A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D6007282-B4F7-4694-AC67-BB838D91B77A}.Release|Any CPU.Build.0 = Release|Any CPU
{D6007282-B4F7-4694-AC67-BB838D91B77A}.Release|x86.ActiveCfg = Release|Any CPU
{D6007282-B4F7-4694-AC67-BB838D91B77A}.Release|x86.ActiveCfg = Release|x86
{D6007282-B4F7-4694-AC67-BB838D91B77A}.Release|x86.Build.0 = Release|x86
{09F295EE-5EDB-4327-ABBE-DDCCDF5EDD9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{09F295EE-5EDB-4327-ABBE-DDCCDF5EDD9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{09F295EE-5EDB-4327-ABBE-DDCCDF5EDD9E}.Debug|x86.ActiveCfg = Debug|x86
{09F295EE-5EDB-4327-ABBE-DDCCDF5EDD9E}.Debug|x86.Build.0 = Debug|x86
{09F295EE-5EDB-4327-ABBE-DDCCDF5EDD9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{09F295EE-5EDB-4327-ABBE-DDCCDF5EDD9E}.Release|Any CPU.Build.0 = Release|Any CPU
{09F295EE-5EDB-4327-ABBE-DDCCDF5EDD9E}.Release|x86.ActiveCfg = Release|x86
{09F295EE-5EDB-4327-ABBE-DDCCDF5EDD9E}.Release|x86.Build.0 = Release|x86
{4074D413-195C-45E9-9E63-0D07914187B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4074D413-195C-45E9-9E63-0D07914187B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4074D413-195C-45E9-9E63-0D07914187B8}.Debug|x86.ActiveCfg = Debug|x86
{4074D413-195C-45E9-9E63-0D07914187B8}.Debug|x86.Build.0 = Debug|x86
{4074D413-195C-45E9-9E63-0D07914187B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4074D413-195C-45E9-9E63-0D07914187B8}.Release|Any CPU.Build.0 = Release|Any CPU
{4074D413-195C-45E9-9E63-0D07914187B8}.Release|x86.ActiveCfg = Release|x86
{4074D413-195C-45E9-9E63-0D07914187B8}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -0,0 +1,114 @@
/*
* WelsonJS.Toolkit: WelsonJS native component
*
* filename:
* BitmapUtils.cs
*
* description:
* WelsonJS - Build a Windows app on the Windows built-in JavaScript engine
*
* website:
* - https://github.com/gnh1201/welsonjs
* - https://catswords.social/@catswords_oss
* - https://teams.live.com/l/community/FEACHncAhq8ldnojAI
*
* author:
* Namhyeon Go <abuse@catswords.net>
*
* license:
* GPLv3 or MS-RL(Microsoft Reciprocal License)
*
*/
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
namespace WelsonJS
{
public class BitmapUtils
{
private static Bitmap Load(string filename)
{
return new Bitmap(filename);
}
public static void Crop(string srcfile, string dstfile, int x, int y, int a, int b)
{
Bitmap originalBitmap = Load(srcfile);
Rectangle cropArea = new Rectangle(x, y, a, b);
Bitmap croppedBitmap = originalBitmap.Clone(cropArea, originalBitmap.PixelFormat);
croppedBitmap.Save(dstfile);
}
public static int[] GetSize(string srcfile)
{
Bitmap bitmap = Load(srcfile);
int width = bitmap.Width;
int height = bitmap.Height;
bitmap.Dispose();
return new int[] { width, height };
}
public static int[] GetPixel(string srcfile, int x, int y)
{
Bitmap bitmap = Load(srcfile);
Color pixelColor = bitmap.GetPixel(x, y);
int red = pixelColor.R;
int green = pixelColor.G;
int blue = pixelColor.B;
bitmap.Dispose();
return new int[] { red, green, blue };
}
public static string GetBase64(string srcfile)
{
Bitmap bitmap = Load(srcfile);
MemoryStream memoryStream = new MemoryStream();
ImageFormat imageFormat;
if (srcfile.EndsWith(".bmp", StringComparison.OrdinalIgnoreCase))
{
imageFormat = ImageFormat.Bmp;
}
else if (srcfile.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) || srcfile.EndsWith(".jpeg", StringComparison.OrdinalIgnoreCase))
{
imageFormat = ImageFormat.Jpeg;
}
else if (srcfile.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
{
imageFormat = ImageFormat.Png;
}
else if (srcfile.EndsWith(".tiff", StringComparison.OrdinalIgnoreCase))
{
imageFormat = ImageFormat.Tiff;
}
else if (srcfile.EndsWith(".gif", StringComparison.OrdinalIgnoreCase))
{
imageFormat = ImageFormat.Gif;
}
else
{
return "";
}
bitmap.Save(memoryStream, imageFormat);
byte[] imageBytes = memoryStream.ToArray();
string base64String = Convert.ToBase64String(imageBytes);
bitmap.Dispose();
memoryStream.Dispose();
return base64String;
}
}
}

View File

@ -0,0 +1,104 @@
/*
* WelsonJS.Toolkit: WelsonJS native component
*
* filename:
* LZ77.cs
*
* description:
* MsCompress(LZ77) algorithm implementation for WelsonJS
*
* website:
* - https://github.com/gnh1201/welsonjs
* - https://catswords.social/@catswords_oss
* - https://teams.live.com/l/community/FEACHncAhq8ldnojAI
*
* author:
* Namhyeon Go <abuse@catswords.net>
*
* license:
* GPLv3 or MS-RL(Microsoft Reciprocal License)
*
*/
using System.Text;
namespace WelsonJS.Compression
{
public class LZ77
{
public static string Compress(string input)
{
StringBuilder compressed = new StringBuilder();
int searchBufferIndex = 0;
while (searchBufferIndex < input.Length)
{
int longestMatchLength = 0;
int longestMatchOffset = 0;
// Search for the longest match in the look-ahead buffer
for (int i = 0; i < searchBufferIndex; i++)
{
int matchLength = 0;
while (matchLength < input.Length - searchBufferIndex && input[i + matchLength] == input[searchBufferIndex + matchLength])
{
matchLength++;
}
if (matchLength > longestMatchLength)
{
longestMatchLength = matchLength;
longestMatchOffset = searchBufferIndex - i;
}
}
// Output the token (offset, length)
if (longestMatchLength > 0)
{
compressed.Append($"({longestMatchOffset},{longestMatchLength})");
searchBufferIndex += longestMatchLength;
}
else
{
compressed.Append($"(0,{input[searchBufferIndex]})");
searchBufferIndex++;
}
}
return compressed.ToString();
}
public static string Decompress(string compressedData)
{
StringBuilder decompressed = new StringBuilder();
int currentIndex = 0;
while (currentIndex < compressedData.Length)
{
if (compressedData[currentIndex] == '(')
{
// Match case
int commaIndex = compressedData.IndexOf(',', currentIndex);
int offset = int.Parse(compressedData.Substring(currentIndex + 1, commaIndex - currentIndex - 1));
int closingParenIndex = compressedData.IndexOf(')', commaIndex);
int length = int.Parse(compressedData.Substring(commaIndex + 1, closingParenIndex - commaIndex - 1));
for (int i = 0; i < length; i++)
{
int copyIndex = decompressed.Length - offset;
decompressed.Append(decompressed[copyIndex]);
}
currentIndex = closingParenIndex + 1;
}
else
{
// Literal case
decompressed.Append(compressedData[currentIndex]);
currentIndex++;
}
}
return decompressed.ToString();
}
}
}

View File

@ -0,0 +1,614 @@
/*
* 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);
}
}
}
}

View File

@ -0,0 +1,132 @@
/*
* 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;
}
}
}

View File

@ -0,0 +1,389 @@
/*
* WelsonJS.Toolkit: WelsonJS native component
*
* filename:
* HIGHT.cs
*
* description:
* HIGHT(ISO/IEC 18033-3) cryptography algorithm 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>
* - @chandong83 (github.com)
* - KISA(Korea Internet & Security Agency) (kisa.or.kr)
* - Korea Unversity (www.korea.ac.kr)
*
* references:
* - https://seed.kisa.or.kr/kisa/algorithm/EgovHightInfo.do
* - https://github.com/chandong83/csharp_crypto_hight_ecb_examples
* - https://blog.naver.com/chandong83/222198351602
* - 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:
* GPLv3 or MS-RL(Microsoft Reciprocal License)
*
*/
using System;
namespace WelsonJS.Cryptography
{
public class HIGHT
{
private static readonly byte[] hightDelta = {
0x5A,0x6D,0x36,0x1B,0x0D,0x06,0x03,0x41,
0x60,0x30,0x18,0x4C,0x66,0x33,0x59,0x2C,
0x56,0x2B,0x15,0x4A,0x65,0x72,0x39,0x1C,
0x4E,0x67,0x73,0x79,0x3C,0x5E,0x6F,0x37,
0x5B,0x2D,0x16,0x0B,0x05,0x42,0x21,0x50,
0x28,0x54,0x2A,0x55,0x6A,0x75,0x7A,0x7D,
0x3E,0x5F,0x2F,0x17,0x4B,0x25,0x52,0x29,
0x14,0x0A,0x45,0x62,0x31,0x58,0x6C,0x76,
0x3B,0x1D,0x0E,0x47,0x63,0x71,0x78,0x7C,
0x7E,0x7F,0x3F,0x1F,0x0F,0x07,0x43,0x61,
0x70,0x38,0x5C,0x6E,0x77,0x7B,0x3D,0x1E,
0x4F,0x27,0x53,0x69,0x34,0x1A,0x4D,0x26,
0x13,0x49,0x24,0x12,0x09,0x04,0x02,0x01,
0x40,0x20,0x10,0x08,0x44,0x22,0x11,0x48,
0x64,0x32,0x19,0x0C,0x46,0x23,0x51,0x68,
0x74,0x3A,0x5D,0x2E,0x57,0x6B,0x35,0x5A
};
private static readonly byte[] hightF0 = {
0x00,0x86,0x0D,0x8B,0x1A,0x9C,0x17,0x91,
0x34,0xB2,0x39,0xBF,0x2E,0xA8,0x23,0xA5,
0x68,0xEE,0x65,0xE3,0x72,0xF4,0x7F,0xF9,
0x5C,0xDA,0x51,0xD7,0x46,0xC0,0x4B,0xCD,
0xD0,0x56,0xDD,0x5B,0xCA,0x4C,0xC7,0x41,
0xE4,0x62,0xE9,0x6F,0xFE,0x78,0xF3,0x75,
0xB8,0x3E,0xB5,0x33,0xA2,0x24,0xAF,0x29,
0x8C,0x0A,0x81,0x07,0x96,0x10,0x9B,0x1D,
0xA1,0x27,0xAC,0x2A,0xBB,0x3D,0xB6,0x30,
0x95,0x13,0x98,0x1E,0x8F,0x09,0x82,0x04,
0xC9,0x4F,0xC4,0x42,0xD3,0x55,0xDE,0x58,
0xFD,0x7B,0xF0,0x76,0xE7,0x61,0xEA,0x6C,
0x71,0xF7,0x7C,0xFA,0x6B,0xED,0x66,0xE0,
0x45,0xC3,0x48,0xCE,0x5F,0xD9,0x52,0xD4,
0x19,0x9F,0x14,0x92,0x03,0x85,0x0E,0x88,
0x2D,0xAB,0x20,0xA6,0x37,0xB1,0x3A,0xBC,
0x43,0xC5,0x4E,0xC8,0x59,0xDF,0x54,0xD2,
0x77,0xF1,0x7A,0xFC,0x6D,0xEB,0x60,0xE6,
0x2B,0xAD,0x26,0xA0,0x31,0xB7,0x3C,0xBA,
0x1F,0x99,0x12,0x94,0x05,0x83,0x08,0x8E,
0x93,0x15,0x9E,0x18,0x89,0x0F,0x84,0x02,
0xA7,0x21,0xAA,0x2C,0xBD,0x3B,0xB0,0x36,
0xFB,0x7D,0xF6,0x70,0xE1,0x67,0xEC,0x6A,
0xCF,0x49,0xC2,0x44,0xD5,0x53,0xD8,0x5E,
0xE2,0x64,0xEF,0x69,0xF8,0x7E,0xF5,0x73,
0xD6,0x50,0xDB,0x5D,0xCC,0x4A,0xC1,0x47,
0x8A,0x0C,0x87,0x01,0x90,0x16,0x9D,0x1B,
0xBE,0x38,0xB3,0x35,0xA4,0x22,0xA9,0x2F,
0x32,0xB4,0x3F,0xB9,0x28,0xAE,0x25,0xA3,
0x06,0x80,0x0B,0x8D,0x1C,0x9A,0x11,0x97,
0x5A,0xDC,0x57,0xD1,0x40,0xC6,0x4D,0xCB,
0x6E,0xE8,0x63,0xE5,0x74,0xF2,0x79,0xFF
};
private static readonly byte[] hightF1 = {
0x00,0x58,0xB0,0xE8,0x61,0x39,0xD1,0x89,
0xC2,0x9A,0x72,0x2A,0xA3,0xFB,0x13,0x4B,
0x85,0xDD,0x35,0x6D,0xE4,0xBC,0x54,0x0C,
0x47,0x1F,0xF7,0xAF,0x26,0x7E,0x96,0xCE,
0x0B,0x53,0xBB,0xE3,0x6A,0x32,0xDA,0x82,
0xC9,0x91,0x79,0x21,0xA8,0xF0,0x18,0x40,
0x8E,0xD6,0x3E,0x66,0xEF,0xB7,0x5F,0x07,
0x4C,0x14,0xFC,0xA4,0x2D,0x75,0x9D,0xC5,
0x16,0x4E,0xA6,0xFE,0x77,0x2F,0xC7,0x9F,
0xD4,0x8C,0x64,0x3C,0xB5,0xED,0x05,0x5D,
0x93,0xCB,0x23,0x7B,0xF2,0xAA,0x42,0x1A,
0x51,0x09,0xE1,0xB9,0x30,0x68,0x80,0xD8,
0x1D,0x45,0xAD,0xF5,0x7C,0x24,0xCC,0x94,
0xDF,0x87,0x6F,0x37,0xBE,0xE6,0x0E,0x56,
0x98,0xC0,0x28,0x70,0xF9,0xA1,0x49,0x11,
0x5A,0x02,0xEA,0xB2,0x3B,0x63,0x8B,0xD3,
0x2C,0x74,0x9C,0xC4,0x4D,0x15,0xFD,0xA5,
0xEE,0xB6,0x5E,0x06,0x8F,0xD7,0x3F,0x67,
0xA9,0xF1,0x19,0x41,0xC8,0x90,0x78,0x20,
0x6B,0x33,0xDB,0x83,0x0A,0x52,0xBA,0xE2,
0x27,0x7F,0x97,0xCF,0x46,0x1E,0xF6,0xAE,
0xE5,0xBD,0x55,0x0D,0x84,0xDC,0x34,0x6C,
0xA2,0xFA,0x12,0x4A,0xC3,0x9B,0x73,0x2B,
0x60,0x38,0xD0,0x88,0x01,0x59,0xB1,0xE9,
0x3A,0x62,0x8A,0xD2,0x5B,0x03,0xEB,0xB3,
0xF8,0xA0,0x48,0x10,0x99,0xC1,0x29,0x71,
0xBF,0xE7,0x0F,0x57,0xDE,0x86,0x6E,0x36,
0x7D,0x25,0xCD,0x95,0x1C,0x44,0xAC,0xF4,
0x31,0x69,0x81,0xD9,0x50,0x08,0xE0,0xB8,
0xF3,0xAB,0x43,0x1B,0x92,0xCA,0x22,0x7A,
0xB4,0xEC,0x04,0x5C,0xD5,0x8D,0x65,0x3D,
0x76,0x2E,0xC6,0x9E,0x17,0x4F,0xA7,0xFF
};
public class ECB
{
//whitening Key [8] + sub Key[128]
byte[] scheduleKey = new byte[136];
public ECB(byte[] userKey)
{
if (userKey.Length < 16)
{
// Pad the key with 0x00 if its length is less than 16 bytes
byte[] paddedKey = new byte[16];
Array.Copy(userKey, 0, paddedKey, 0, userKey.Length);
userKey = paddedKey;
}
else if (userKey.Length > 16)
{
// If the key is longer than 16 bytes, truncate to 16 bytes
byte[] truncatedKey = new byte[16];
Array.Copy(userKey, truncatedKey, 16);
userKey = truncatedKey;
}
KeySched(userKey);
}
void KeySched(byte[] userKey)
{
for (int i = 0; i < 4; i++)
{
scheduleKey[i] = userKey[i + 12];
scheduleKey[i + 4] = userKey[i];
}
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
scheduleKey[8 + 16 * i + j] = (byte)((userKey[(j - i) & 7] + hightDelta[(16 * i + j)]) & 0xFF);
}
for (int j = 0; j < 8; j++)
{
scheduleKey[8 + 16 * i + j + 8] = (byte)((userKey[((j - i) & 7) + 8] + hightDelta[16 * i + j + 8]) & 0xFF);
}
}
}
void DecryptBlock(byte[] dataIn, byte[] dataOut)
{
byte[] xx = new byte[8];
xx[2] = dataIn[1];
xx[4] = dataIn[3];
xx[6] = dataIn[5];
xx[0] = dataIn[7];
//void HIGHT_DEC(byte[] scheduleKey, byte[] xx, int k, int i0, int i1, int i2, int i3, int i4, int i5, int i6, int i7)
void HIGHT_DEC(int k, int i0, int i1, int i2, int i3, int i4, int i5, int i6, int i7)
{
xx[i1] = (byte)((xx[i1] - (hightF1[xx[i2]] ^ scheduleKey[4 * k + 2])) & 0xFF);
xx[i3] = (byte)((xx[i3] ^ (hightF0[xx[i4]] + scheduleKey[4 * k + 1])) & 0xFF);
xx[i5] = (byte)((xx[i5] - (hightF1[xx[i6]] ^ scheduleKey[4 * k + 0])) & 0xFF);
xx[i7] = (byte)((xx[i7] ^ (hightF0[xx[i0]] + scheduleKey[4 * k + 3])) & 0xFF);
}
xx[1] = (byte)(dataIn[0] - scheduleKey[4]);
xx[3] = (byte)(dataIn[2] ^ scheduleKey[5]);
xx[5] = (byte)(dataIn[4] - scheduleKey[6]);
xx[7] = (byte)(dataIn[6] ^ scheduleKey[7]);
HIGHT_DEC(33, 7, 6, 5, 4, 3, 2, 1, 0);
HIGHT_DEC(32, 0, 7, 6, 5, 4, 3, 2, 1);
HIGHT_DEC(31, 1, 0, 7, 6, 5, 4, 3, 2);
HIGHT_DEC(30, 2, 1, 0, 7, 6, 5, 4, 3);
HIGHT_DEC(29, 3, 2, 1, 0, 7, 6, 5, 4);
HIGHT_DEC(28, 4, 3, 2, 1, 0, 7, 6, 5);
HIGHT_DEC(27, 5, 4, 3, 2, 1, 0, 7, 6);
HIGHT_DEC(26, 6, 5, 4, 3, 2, 1, 0, 7);
HIGHT_DEC(25, 7, 6, 5, 4, 3, 2, 1, 0);
HIGHT_DEC(24, 0, 7, 6, 5, 4, 3, 2, 1);
HIGHT_DEC(23, 1, 0, 7, 6, 5, 4, 3, 2);
HIGHT_DEC(22, 2, 1, 0, 7, 6, 5, 4, 3);
HIGHT_DEC(21, 3, 2, 1, 0, 7, 6, 5, 4);
HIGHT_DEC(20, 4, 3, 2, 1, 0, 7, 6, 5);
HIGHT_DEC(19, 5, 4, 3, 2, 1, 0, 7, 6);
HIGHT_DEC(18, 6, 5, 4, 3, 2, 1, 0, 7);
HIGHT_DEC(17, 7, 6, 5, 4, 3, 2, 1, 0);
HIGHT_DEC(16, 0, 7, 6, 5, 4, 3, 2, 1);
HIGHT_DEC(15, 1, 0, 7, 6, 5, 4, 3, 2);
HIGHT_DEC(14, 2, 1, 0, 7, 6, 5, 4, 3);
HIGHT_DEC(13, 3, 2, 1, 0, 7, 6, 5, 4);
HIGHT_DEC(12, 4, 3, 2, 1, 0, 7, 6, 5);
HIGHT_DEC(11, 5, 4, 3, 2, 1, 0, 7, 6);
HIGHT_DEC(10, 6, 5, 4, 3, 2, 1, 0, 7);
HIGHT_DEC(9, 7, 6, 5, 4, 3, 2, 1, 0);
HIGHT_DEC(8, 0, 7, 6, 5, 4, 3, 2, 1);
HIGHT_DEC(7, 1, 0, 7, 6, 5, 4, 3, 2);
HIGHT_DEC(6, 2, 1, 0, 7, 6, 5, 4, 3);
HIGHT_DEC(5, 3, 2, 1, 0, 7, 6, 5, 4);
HIGHT_DEC(4, 4, 3, 2, 1, 0, 7, 6, 5);
HIGHT_DEC(3, 5, 4, 3, 2, 1, 0, 7, 6);
HIGHT_DEC(2, 6, 5, 4, 3, 2, 1, 0, 7);
dataOut[1] = (byte)(xx[1] & 0xFF);
dataOut[3] = (byte)(xx[3] & 0xFF);
dataOut[5] = (byte)(xx[5] & 0xFF);
dataOut[7] = (byte)(xx[7] & 0xFF);
dataOut[0] = (byte)((xx[0] - scheduleKey[0]) & 0xFF);
dataOut[2] = (byte)((xx[2] ^ scheduleKey[1]) & 0xFF);
dataOut[4] = (byte)((xx[4] - scheduleKey[2]) & 0xFF);
dataOut[6] = (byte)((xx[6] ^ scheduleKey[3]) & 0xFF);
}
void EncryptBlock(byte[] dataIn, byte[] dataOut)
{
byte[] xx = new byte[8];
xx[1] = dataIn[1];
xx[3] = dataIn[3];
xx[5] = dataIn[5];
xx[7] = dataIn[7];
xx[0] = (byte)((dataIn[0] + scheduleKey[0]) & 0xFF);
xx[2] = (byte)((dataIn[2] ^ scheduleKey[1]));
xx[4] = (byte)((dataIn[4] + scheduleKey[2]) & 0xFF);
xx[6] = (byte)((dataIn[6] ^ scheduleKey[3]));
void HIGHT_ENC(int k, int i0, int i1, int i2, int i3, int i4, int i5, int i6, int i7)
{
xx[i0] = (byte)((xx[i0] ^ (hightF0[xx[i1]] + scheduleKey[4 * k + 3])) & 0xFF);
xx[i2] = (byte)((xx[i2] + (hightF1[xx[i3]] ^ scheduleKey[4 * k + 2])) & 0xFF);
xx[i4] = (byte)((xx[i4] ^ (hightF0[xx[i5]] + scheduleKey[4 * k + 1])) & 0xFF);
xx[i6] = (byte)((xx[i6] + (hightF1[xx[i7]] ^ scheduleKey[4 * k + 0])) & 0xFF);
}
HIGHT_ENC(2, 7, 6, 5, 4, 3, 2, 1, 0);
HIGHT_ENC(3, 6, 5, 4, 3, 2, 1, 0, 7);
HIGHT_ENC(4, 5, 4, 3, 2, 1, 0, 7, 6);
HIGHT_ENC(5, 4, 3, 2, 1, 0, 7, 6, 5);
HIGHT_ENC(6, 3, 2, 1, 0, 7, 6, 5, 4);
HIGHT_ENC(7, 2, 1, 0, 7, 6, 5, 4, 3);
HIGHT_ENC(8, 1, 0, 7, 6, 5, 4, 3, 2);
HIGHT_ENC(9, 0, 7, 6, 5, 4, 3, 2, 1);
HIGHT_ENC(10, 7, 6, 5, 4, 3, 2, 1, 0);
HIGHT_ENC(11, 6, 5, 4, 3, 2, 1, 0, 7);
HIGHT_ENC(12, 5, 4, 3, 2, 1, 0, 7, 6);
HIGHT_ENC(13, 4, 3, 2, 1, 0, 7, 6, 5);
HIGHT_ENC(14, 3, 2, 1, 0, 7, 6, 5, 4);
HIGHT_ENC(15, 2, 1, 0, 7, 6, 5, 4, 3);
HIGHT_ENC(16, 1, 0, 7, 6, 5, 4, 3, 2);
HIGHT_ENC(17, 0, 7, 6, 5, 4, 3, 2, 1);
HIGHT_ENC(18, 7, 6, 5, 4, 3, 2, 1, 0);
HIGHT_ENC(19, 6, 5, 4, 3, 2, 1, 0, 7);
HIGHT_ENC(20, 5, 4, 3, 2, 1, 0, 7, 6);
HIGHT_ENC(21, 4, 3, 2, 1, 0, 7, 6, 5);
HIGHT_ENC(22, 3, 2, 1, 0, 7, 6, 5, 4);
HIGHT_ENC(23, 2, 1, 0, 7, 6, 5, 4, 3);
HIGHT_ENC(24, 1, 0, 7, 6, 5, 4, 3, 2);
HIGHT_ENC(25, 0, 7, 6, 5, 4, 3, 2, 1);
HIGHT_ENC(26, 7, 6, 5, 4, 3, 2, 1, 0);
HIGHT_ENC(27, 6, 5, 4, 3, 2, 1, 0, 7);
HIGHT_ENC(28, 5, 4, 3, 2, 1, 0, 7, 6);
HIGHT_ENC(29, 4, 3, 2, 1, 0, 7, 6, 5);
HIGHT_ENC(30, 3, 2, 1, 0, 7, 6, 5, 4);
HIGHT_ENC(31, 2, 1, 0, 7, 6, 5, 4, 3);
HIGHT_ENC(32, 1, 0, 7, 6, 5, 4, 3, 2);
HIGHT_ENC(33, 0, 7, 6, 5, 4, 3, 2, 1);
dataOut[1] = (byte)(xx[2] & 0xFF);
dataOut[3] = (byte)(xx[4] & 0xFF);
dataOut[5] = (byte)(xx[6] & 0xFF);
dataOut[7] = (byte)(xx[0] & 0xFF);
dataOut[0] = (byte)((xx[1] + scheduleKey[4]) & 0xFF);
dataOut[2] = (byte)((xx[3] ^ scheduleKey[5]) & 0xFF);
dataOut[4] = (byte)((xx[5] + scheduleKey[6]) & 0xFF);
dataOut[6] = (byte)((xx[7] ^ scheduleKey[7]) & 0xFF);
}
public byte[] Encrypt(byte[] dataIn)
{
int length;
if (dataIn.Length == 0)
{
return null;
}
if ((dataIn.Length % 8) != 0)
{
length = dataIn.Length + (8 - (dataIn.Length % 8));
}
else
{
length = dataIn.Length;
}
byte[] dataOut = new byte[length];
byte[] tempIn = new byte[8];
byte[] tempOut = new byte[8];
byte[] dataInWithPadding = new byte[length];
Array.Copy(dataIn, dataInWithPadding, dataIn.Length);
for (int i = 0; i < (int)(length / 8); i++)
{
Array.Copy(dataInWithPadding, i * 8, tempIn, 0, 8);
EncryptBlock(tempIn, tempOut);
Array.Copy(tempOut, 0, dataOut, i * 8, 8);
}
return dataOut;
}
public byte[] Decrypt(byte[] dataIn)
{
int length;
if (dataIn.Length == 0)
{
return null;
}
if ((dataIn.Length % 8) != 0)
{
length = dataIn.Length + (8 - (dataIn.Length % 8));
}
else
{
length = dataIn.Length;
}
byte[] dataOut = new byte[length];
byte[] tempIn = new byte[8];
byte[] tempOut = new byte[8];
byte[] dataInWithPadding = new byte[length];
Array.Copy(dataIn, dataInWithPadding, dataIn.Length);
for (int i = 0; i < (int)(length / 8); i++)
{
Array.Copy(dataInWithPadding, i * 8, tempIn, 0, 8);
DecryptBlock(tempIn, tempOut);
Array.Copy(tempOut, 0, dataOut, i * 8, 8);
}
return dataOut;
}
public void Test()
{
byte[] dataIn = new byte[15];
byte[] dataOut = new byte[15];
byte[] dataOut2 = new byte[15];
for (int i = 0; i < 15; i++)
{
dataIn[i] = (byte)i;
}
Console.WriteLine("schedule key data");
Console.WriteLine(string.Format("0x{0:x2}", scheduleKey));
dataOut = Encrypt(dataIn);
dataOut2 = Decrypt(dataOut);
Console.WriteLine("origin data");
Console.WriteLine(string.Format("0x{0:x2}", dataIn));
Console.WriteLine("encryption data");
Console.WriteLine(string.Format("0x{0:x2}", dataOut));
Console.WriteLine("decryption data");
Console.WriteLine(string.Format("0x{0:x2}", dataOut2));
}
}
}
}

View File

@ -0,0 +1,349 @@
/*
* 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);
}
}
}
}

View File

@ -0,0 +1,118 @@
/*
* 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;
}
}
}

View File

@ -0,0 +1,755 @@
/*
* 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;
}
}
}
}

View File

@ -0,0 +1,198 @@
/*
* WelsonJS.Toolkit: WelsonJS native component
*
* filename:
* NamedSharedMemory.cs
*
* description:
* WelsonJS - Build a Windows app on the Windows built-in JavaScript engine
*
* website:
* - https://github.com/gnh1201/welsonjs
* - https://catswords.social/@catswords_oss
* - https://teams.live.com/l/community/FEACHncAhq8ldnojAI
*
* author:
* Namhyeon Go <abuse@catswords.net>
*
* license:
* GPLv3 or MS-RL(Microsoft Reciprocal License)
*
*/
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace WelsonJS
{
public class NamedSharedMemory
{
private IntPtr hFile;
private IntPtr hFileMappingObject;
private string lpName;
private static Dictionary<string, NamedSharedMemory> memoryMap = new Dictionary<string, NamedSharedMemory>();
[Flags]
public enum FileProtection : uint
{
PAGE_NOACCESS = 1u,
PAGE_READONLY = 2u,
PAGE_READWRITE = 4u,
PAGE_WRITECOPY = 8u,
PAGE_EXECUTE = 0x10u,
PAGE_EXECUTE_READ = 0x20u,
PAGE_EXECUTE_READWRITE = 0x40u,
PAGE_EXECUTE_WRITECOPY = 0x80u,
PAGE_GUARD = 0x100u,
PAGE_NOCACHE = 0x200u,
PAGE_WRITECOMBINE = 0x400u,
SEC_FILE = 0x800000u,
SEC_IMAGE = 0x1000000u,
SEC_RESERVE = 0x4000000u,
SEC_COMMIT = 0x8000000u,
SEC_NOCACHE = 0x10000000u
}
[Flags]
public enum FileMapAccess
{
FILE_MAP_COPY = 1,
FILE_MAP_WRITE = 2,
FILE_MAP_READ = 4,
FILE_MAP_ALL_ACCESS = 0xF001F
}
public class FileMappingNative
{
public const int INVALID_HANDLE_VALUE = -1;
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateFileMapping(IntPtr hFile, IntPtr lpAttributes, FileProtection flProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow, string lpName);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr MapViewOfFile(IntPtr hFileMappingObject, FileMapAccess dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenFileMapping(FileMapAccess dwDesiredAccess, bool bInheritHandle, string lpName);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnmapViewOfFile(IntPtr lpBaseAddress);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hHandle);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint GetLastError();
}
public NamedSharedMemory(string lpName)
{
this.lpName = lpName;
Open();
}
public bool Open()
{
if (memoryMap.ContainsKey(lpName))
{
hFile = memoryMap[lpName].hFile;
hFileMappingObject = memoryMap[lpName].hFileMappingObject;
return true;
}
try
{
hFile = FileMappingNative.CreateFileMapping((IntPtr)(-1), IntPtr.Zero, FileProtection.PAGE_READWRITE, 0u, 1024u, lpName);
hFileMappingObject = FileMappingNative.MapViewOfFile(hFile, FileMapAccess.FILE_MAP_ALL_ACCESS, 0u, 0u, 1024u);
memoryMap.Add(lpName, this);
}
catch
{
return false;
}
return IsInitialized();
}
public bool IsInitialized()
{
return hFile != IntPtr.Zero;
}
public string ReadText()
{
try
{
if (hFile == IntPtr.Zero || hFileMappingObject == IntPtr.Zero)
{
throw new Exception("Could not access the shared memory");
}
return Marshal.PtrToStringAnsi(hFileMappingObject);
}
catch (Exception e)
{
return "Exception: " + e.Message;
}
}
public bool WriteText(string text, int size = 1024)
{
try
{
if (hFile == IntPtr.Zero || hFileMappingObject == IntPtr.Zero)
{
throw new Exception("Could not access the shared memory");
}
byte[] bytes = Encoding.ASCII.GetBytes(text);
byte[] array = new byte[size + 1];
Array.Copy(bytes, array, bytes.Length);
Marshal.Copy(array, 0, hFileMappingObject, size);
}
catch
{
return false;
}
return true;
}
public bool Clear(int size = 1024)
{
try
{
Marshal.Copy(new byte[size + 1], 0, hFileMappingObject, size);
}
catch
{
return false;
}
return true;
}
public bool Close()
{
try
{
if (hFile == IntPtr.Zero || hFileMappingObject == IntPtr.Zero)
{
throw new Exception("Could not access the shared memory");
}
FileMappingNative.UnmapViewOfFile(hFileMappingObject);
hFileMappingObject = IntPtr.Zero;
FileMappingNative.CloseHandle(hFile);
hFile = IntPtr.Zero;
}
catch
{
return false;
}
return true;
}
}
}

View File

@ -0,0 +1,90 @@
/*
* WelsonJS.Toolkit: WelsonJS native component
*
* filename:
* ProcessUtils.cs
*
* description:
* WelsonJS - Build a Windows app on the Windows built-in JavaScript engine
*
* website:
* - https://github.com/gnh1201/welsonjs
* - https://catswords.social/@catswords_oss
* - https://teams.live.com/l/community/FEACHncAhq8ldnojAI
*
* author:
* Namhyeon Go <abuse@catswords.net>
*
* license:
* GPLv3 or MS-RL(Microsoft Reciprocal License)
*
*/
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows.Forms;
namespace WelsonJS
{
public class ProcessUtils
{
public static List<Process> ProcessList = new List<Process>();
public static string OpenFileDialog()
{
string filepath = string.Empty;
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.Filter = "All files (*.*)|*.*";
openFileDialog.RestoreDirectory = true;
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
filepath = openFileDialog.FileName;
}
}
return filepath;
}
public static int Open(string filepath)
{
int processId = -1;
if (string.IsNullOrEmpty(filepath))
{
filepath = OpenFileDialog();
if (string.IsNullOrEmpty(filepath))
{
return processId;
}
}
try
{
Process process = new Process();
process.StartInfo.FileName = filepath;
process.Start();
ProcessList.Add(process);
}
catch {
processId = -1;
}
return processId;
}
public static bool Close(int processId)
{
try
{
Process.GetProcessById(processId).CloseMainWindow();
}
catch
{
return false;
}
return true;
}
}
}

View File

@ -1,4 +1,25 @@
using System.Windows.Forms;
/*
* WelsonJS.Toolkit: WelsonJS native component
*
* filename:
* Prompt.cs
*
* description:
* WelsonJS - Build a Windows app on the Windows built-in JavaScript engine
*
* website:
* - https://github.com/gnh1201/welsonjs
* - https://catswords.social/@catswords_oss
* - https://teams.live.com/l/community/FEACHncAhq8ldnojAI
*
* author:
* Namhyeon Go <abuse@catswords.net>
*
* license:
* GPLv3 or MS-RL(Microsoft Reciprocal License)
*
*/
using System.Windows.Forms;
namespace WelsonJS
{
@ -14,7 +35,7 @@ namespace WelsonJS
Text = caption,
StartPosition = FormStartPosition.CenterScreen
};
Label textLabel = new Label() { Left = 50, Top = 20, Text = text };
Label textLabel = new Label() { Left = 50, Top = 20, Width = 400, Text = text };
TextBox textBox = new TextBox() { Left = 50, Top = 50, Width = 400 };
Button confirmation = new Button() { Text = "Ok", Left = 350, Width = 100, Top = 70, DialogResult = DialogResult.OK };
confirmation.Click += (sender, e) => { prompt.Close(); };

View File

@ -6,12 +6,12 @@ using System.Runtime.InteropServices;
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
// 이러한 특성 값을 변경하세요.
[assembly: AssemblyTitle("WelsonJS.Toolkit")]
[assembly: AssemblyDescription("WelsonJS CSharp.NET native component")]
[assembly: AssemblyDescription("Toolkit for WelsonJS framework based applications")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("gnh1201/welsonjs")]
[assembly: AssemblyProduct("WelsonJS.Toolkit")]
[assembly: AssemblyCopyright("gnh1201/welsonjs is licensed under the Microsoft Public License (Ms-PL)")]
[assembly: AssemblyTrademark("WelsonJS.Toolkit")]
[assembly: AssemblyCompany("Catswords")]
[assembly: AssemblyProduct("WelsonJS")]
[assembly: AssemblyCopyright("Catswords OSS, GPLv3 or Ms-RL")]
[assembly: AssemblyTrademark("WelsonJS")]
[assembly: AssemblyCulture("")]
// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
// 기본값으로 할 수 있습니다.
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("0.2.7.54")]
[assembly: AssemblyFileVersion("0.2.7.54")]

View File

@ -0,0 +1,28 @@
using System.Collections.Generic;
using System.Text;
namespace WelsonJS.Serialization
{
public class KVSerializer
{
private static Dictionary<string, string> dict = new Dictionary<string, string>();
public void Add(string key, string value)
{
dict[key] = value;
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
foreach (var x in dict)
{
sb.Append($"{x.Key}={x.Value}; ");
}
if (sb.Length > 0) sb.Length -= 2;
return sb.ToString();
}
}
}

View File

@ -0,0 +1,74 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
// TinyINIController
// Original source code: https://github.com/niklyadov/tiny-ini-file-class
namespace WelsonJS.TinyINIController
{
public class IniFile
{
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
static extern long WritePrivateProfileString(string section, string key, string value, string FilePath);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
static extern int GetPrivateProfileString(string section, string key, string Default, StringBuilder RetVal, int Size, string FilePath);
private readonly FileInfo FileInfo;
//private readonly string exe = Assembly.GetExecutingAssembly().GetName().Name;
private readonly string defaultSection = "Default";
private readonly FileAccess fileAccess;
public IniFile(string path = null, FileAccess access = FileAccess.ReadWrite)
{
fileAccess = access;
FileInfo = new FileInfo(path ?? defaultSection);
}
public string Read(string key, string section = null)
{
var RetVal = new StringBuilder(65025);
if (fileAccess != FileAccess.Write)
{
GetPrivateProfileString(section ?? defaultSection, key, "", RetVal, 65025, FileInfo.FullName);
}
else
{
throw new Exception("Can`t read file! No access!");
}
return RetVal.ToString();
}
public void Write(string key, string value, string section = null)
{
if (fileAccess != FileAccess.Read)
{
WritePrivateProfileString(section ?? defaultSection, key, value, FileInfo.FullName);
}
else
{
throw new Exception("Can`t write to file! No access!");
}
}
public void DeleteKey(string key, string section = null)
{
Write(key, null, section ?? defaultSection);
}
public void DeleteSection(string section = null)
{
Write(null, null, section ?? defaultSection);
}
public bool KeyExists(string key, string section = null)
{
return Read(key, section).Length > 0;
}
}
}

View File

@ -1,15 +1,22 @@
/*
* WelsonJS.Toolkit: WelsonJS C#.NET native component
* WelsonJS.Toolkit: WelsonJS native component
*
* filename:
* Toolkit.cs
*
* description:
* WelsonJS - Build Windows desktop apps with JavaScript, HTML, and CSS based on WSH/HTA.
* https://github.com/gnh1201/welsonjs
* WelsonJS - Build a Windows app on the Windows built-in JavaScript engine
*
* website:
* - https://github.com/gnh1201/welsonjs
* - https://catswords.social/@catswords_oss
* - https://teams.live.com/l/community/FEACHncAhq8ldnojAI
*
* author:
* Namhyeon Go <abuse@catswords.net>
*
* license:
* gnh1201/welsonjs is licensed under the Microsoft Reciprocal License (MS-RL)
* GPLv3 or MS-RL(Microsoft Reciprocal License)
*
* references:
* - https://stackoverflow.com/questions/9004352/call-a-function-in-a-console-app-from-vbscript
@ -23,122 +30,55 @@
*/
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using WelsonJS.Cryptography;
using WelsonJS.Serialization;
namespace WelsonJS
{
[ComVisible(true)]
public class Toolkit
{
private static string ApplicationName = "WelsonJS";
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern IntPtr FindWindowEx(IntPtr hWnd1, IntPtr hWnd2, string lpsz1, string lpsz2);
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, uint msg, int wParam, IntPtr lParam);
public enum WMessages : int
{
WM_MOUSEMOVE = 0x200,
WM_LBUTTONDOWN = 0x201, //Left mousebutton down
WM_LBUTTONUP = 0x202, //Left mousebutton up
WM_LBUTTONDBLCLK = 0x203, //Left mousebutton doubleclick
WM_RBUTTONDOWN = 0x204, //Right mousebutton down
WM_RBUTTONUP = 0x205, //Right mousebutton up
WM_RBUTTONDBLCLK = 0x206, //Right mousebutton doubleclick
WM_KEYDOWN = 0x100, //Key down
WM_KEYUP = 0x101, //Key up
WM_SYSKEYDOWN = 0x104,
WM_SYSKEYUP = 0x105,
WM_CHAR = 0x102, //char
WM_COMMAND = 0x111
}
public enum WVirtualKeys : int
{
VK_RETURN = 0x0D,
VK_F1 = 0x70,
VK_F2 = 0x71,
VK_F3 = 0x72,
VK_F4 = 0x73,
VK_F5 = 0x74,
VK_F6 = 0x75,
VK_F7 = 0x76,
VK_F8 = 0x77,
VK_F9 = 0x78,
VK_F10 = 0x79,
VK_F11 = 0x7A,
VK_F12 = 0x7B
}
public IntPtr QueryHandleWindow(string wName)
{
IntPtr hWnd = IntPtr.Zero;
foreach (Process pList in Process.GetProcesses())
{
if (pList.MainWindowTitle.Contains(wName))
{
hWnd = pList.MainWindowHandle;
break;
}
}
return hWnd;
}
public static readonly string ApplicationName = "WelsonJS";
[ComVisible(true)]
public bool SendClick(string wName, int X, int Y)
public bool SendClick(string title, int x, int y)
{
bool result = false;
IntPtr hWnd = QueryHandleWindow(wName);
IntPtr hWnd = Window.GetWindowByTitleContains(title);
if (hWnd != IntPtr.Zero) {
PostMessage(hWnd, (int)WMessages.WM_LBUTTONDOWN, 1, new IntPtr(Y * 0x10000 + X));
PostMessage(hWnd, (int)WMessages.WM_LBUTTONUP, 0, new IntPtr(Y * 0x10000 + X));
result = true;
Window.PostMessage(hWnd, (int)Window.Message.WM_LBUTTONDOWN, 1, new IntPtr(y * 0x10000 + x));
Window.PostMessage(hWnd, (int)Window.Message.WM_LBUTTONUP, 0, new IntPtr(y * 0x10000 + x));
}
return result;
return hWnd != IntPtr.Zero;
}
[ComVisible(true)]
public bool SendKey(string wName, char key)
public bool SendKey(string title, char key)
{
IntPtr hWnd = QueryHandleWindow(wName);
IntPtr hWnd = Window.GetWindowByTitleContains(title);
return SendKey(hWnd, key);
}
// [ComVisible(false)]
public bool SendKey(IntPtr hWnd, char key)
{
return PostMessage(hWnd, (int)WMessages.WM_CHAR, key, IntPtr.Zero);
return Window.PostMessage(hWnd, (int)Window.Message.WM_CHAR, key, IntPtr.Zero);
}
[ComVisible(true)]
public bool SendKeys(string wName, string str)
public bool SendKeys(string title, string str)
{
bool result = false;
IntPtr hWnd = QueryHandleWindow(wName);
IntPtr hWnd = Window.GetWindowByTitleContains(title);
if (hWnd != IntPtr.Zero)
{
foreach (char i in str)
{
SendKey(hWnd, i);
}
result = true;
foreach (char i in str) SendKey(hWnd, i);
return true;
}
return result;
return false;
}
[ComVisible(true)]
@ -162,55 +102,183 @@ namespace WelsonJS
}
[ComVisible(true)]
public bool SendEnterKey(string wName)
public bool SendEnterKey(string title)
{
IntPtr hWnd = QueryHandleWindow(wName);
IntPtr hWnd = Window.GetWindowByTitleContains(title);
if (hWnd != IntPtr.Zero)
{
PostMessage(hWnd, (int)WMessages.WM_KEYDOWN, (char)WVirtualKeys.VK_RETURN, IntPtr.Zero);
PostMessage(hWnd, (int)WMessages.WM_KEYUP, (char)WVirtualKeys.VK_RETURN, IntPtr.Zero);
Window.PostMessage(hWnd, (int)Window.Message.WM_KEYDOWN, (char)Window.VirtualKey.VK_RETURN, IntPtr.Zero);
Window.PostMessage(hWnd, (int)Window.Message.WM_KEYUP, (char)Window.VirtualKey.VK_RETURN, IntPtr.Zero);
return true;
}
else
{
return false;
}
return false;
}
[ComVisible(true)]
public bool SendFnKey(string wName, int num) {
IntPtr hWnd = QueryHandleWindow(wName);
char cKey = (char)0x00;
if (hWnd != IntPtr.Zero)
public bool SendFnKey(string title, int num) {
char[] fnKeys = new char[]
{
switch (num) {
case 1: cKey = (char)WVirtualKeys.VK_F1; break;
case 2: cKey = (char)WVirtualKeys.VK_F2; break;
case 3: cKey = (char)WVirtualKeys.VK_F3; break;
case 4: cKey = (char)WVirtualKeys.VK_F4; break;
case 5: cKey = (char)WVirtualKeys.VK_F5; break;
case 6: cKey = (char)WVirtualKeys.VK_F6; break;
case 7: cKey = (char)WVirtualKeys.VK_F7; break;
case 8: cKey = (char)WVirtualKeys.VK_F8; break;
case 9: cKey = (char)WVirtualKeys.VK_F9; break;
case 10: cKey = (char)WVirtualKeys.VK_F10; break;
case 11: cKey = (char)WVirtualKeys.VK_F11; break;
case 12: cKey = (char)WVirtualKeys.VK_F12; break;
}
if (cKey != 0x00) {
PostMessage(hWnd, (int)WMessages.WM_KEYDOWN, cKey, IntPtr.Zero);
PostMessage(hWnd, (int)WMessages.WM_KEYUP, cKey, IntPtr.Zero);
}
(char)0x00,
(char)Window.VirtualKey.VK_F1,
(char)Window.VirtualKey.VK_F2,
(char)Window.VirtualKey.VK_F3,
(char)Window.VirtualKey.VK_F4,
(char)Window.VirtualKey.VK_F5,
(char)Window.VirtualKey.VK_F6,
(char)Window.VirtualKey.VK_F7,
(char)Window.VirtualKey.VK_F8,
(char)Window.VirtualKey.VK_F9,
(char)Window.VirtualKey.VK_F10,
(char)Window.VirtualKey.VK_F11,
(char)Window.VirtualKey.VK_F12
};
IntPtr hWnd = Window.GetWindowByTitleContains(title);
if (hWnd != IntPtr.Zero && (fnKeys.Length + 1 < num))
{
Window.PostMessage(hWnd, (int)Window.Message.WM_KEYDOWN, fnKeys[num], IntPtr.Zero);
Window.PostMessage(hWnd, (int)Window.Message.WM_KEYUP, fnKeys[num], IntPtr.Zero);
return true;
}
else
return false;
}
// [Toolkit] Access to a shared memory #96
[ComVisible(true)]
public bool WriteTextToSharedMemory(string lpName, string text)
{
NamedSharedMemory mem = new NamedSharedMemory(lpName);
if (mem.IsInitialized())
{
return false;
return mem.WriteText(text);
}
return false;
}
[ComVisible(true)]
public string ReadTextFromSharedMemory(string lpName)
{
NamedSharedMemory mem = new NamedSharedMemory(lpName);
if (mem.IsInitialized()) {
return mem.ReadText();
}
return "";
}
[ComVisible(true)]
public bool ClearSharedMemory(string lpName)
{
NamedSharedMemory mem = new NamedSharedMemory(lpName);
if (mem.IsInitialized())
{
return mem.Clear();
}
return false;
}
[ComVisible(true)]
public bool CloseSharedMemory(string lpName)
{
NamedSharedMemory mem = new NamedSharedMemory(lpName);
if (mem.IsInitialized())
{
return mem.Close();
}
return false;
}
[ComVisible(true)]
public string GetFilePathFromDialog()
{
return ProcessUtils.OpenFileDialog();
}
[ComVisible(true)]
public int OpenProcess(string filepath)
{
return ProcessUtils.Open(filepath);
}
[ComVisible(true)]
public bool CloseProcess(int processID)
{
return ProcessUtils.Close(processID);
}
[ComVisible(true)]
public string CompressLZ77(string data)
{
return Compression.LZ77.Compress(data);
}
[ComVisible(true)]
public string DecompressLZ77(string compressedData)
{
return Compression.LZ77.Decompress(compressedData);
}
[ComVisible(true)]
public string EncryptString(string key, string data)
{
byte[] userKey = Encoding.ASCII.GetBytes(key);
byte[] dataIn = Encoding.UTF8.GetBytes(data);
HIGHT.ECB cipher = new HIGHT.ECB(userKey);
return Convert.ToBase64String(cipher.Encrypt(dataIn));
}
[ComVisible(true)]
public string DecryptString(string key, string encryptedData)
{
byte[] userKey = Encoding.ASCII.GetBytes(key);
byte[] dataIn = Convert.FromBase64String(encryptedData);
HIGHT.ECB cipher = new HIGHT.ECB(userKey);
return Encoding.UTF8.GetString(cipher.Decrypt(dataIn)).Trim('\0');
}
[ComVisible(true)]
public string GetImageSize(string srcfile)
{
int[] result = BitmapUtils.GetSize(srcfile);
var serializer = new KVSerializer();
serializer.Add("width", result[0].ToString());
serializer.Add("height", result[1].ToString());
return serializer.ToString();
}
[ComVisible(true)]
public string GetImagePixel(string srcfile)
{
int[] result = BitmapUtils.GetSize(srcfile);
var serializer = new KVSerializer();
serializer.Add("red", result[0].ToString());
serializer.Add("green", result[1].ToString());
serializer.Add("blue", result[2].ToString());
return serializer.ToString();
}
[ComVisible(true)]
public string GetImageBase64(string srcfile)
{
return BitmapUtils.GetBase64(srcfile);
}
[ComVisible(true)]
public void CropImage(string srcfile, string dstfile, int x, int y, int a, int b)
{
BitmapUtils.Crop(srcfile, dstfile, x, y, a, b);
}
}
}

View File

@ -41,18 +41,76 @@
<PropertyGroup>
<AssemblyOriginatorKeyFile>welsonjs.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>favicon.ico</ApplicationIcon>
<PackageIcon>icon.png</PackageIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
</ItemGroup>
<ItemGroup>
<Compile Include="BitmapUtils.cs" />
<Compile Include="Compression\LZ77.cs" />
<Compile Include="Cryptography\AnsiX923Padding.cs" />
<Compile Include="Cryptography\ARIA.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="ProcessUtils.cs" />
<Compile Include="Prompt.cs" />
<Compile Include="Serialization\KVSerializer.cs" />
<Compile Include="TinyINIController\IniFile.cs" />
<Compile Include="Toolkit.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Window.cs" />
</ItemGroup>
<ItemGroup>
<None Include="welsonjs.snk" />
<None Include="WelsonJS.Toolkit.nuspec" />
<None Include="assets/img/logo.png" Pack="true" PackagePath="" />
</ItemGroup>
<ItemGroup>
<Content Include="favicon.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -0,0 +1,22 @@
<?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>

View File

@ -0,0 +1,92 @@
/*
* WelsonJS.Toolkit: WelsonJS native component
*
* filename:
* Window.cs
*
* description:
* WelsonJS - Build a Windows app on the Windows built-in JavaScript engine
*
* website:
* - https://github.com/gnh1201/welsonjs
* - https://catswords.social/@catswords_oss
* - https://teams.live.com/l/community/FEACHncAhq8ldnojAI
*
* author:
* Namhyeon Go <abuse@catswords.net>
*
* license:
* GPLv3 or MS-RL(Microsoft Reciprocal License)
*
*/
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace WelsonJS
{
public class Window
{
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern IntPtr FindWindowEx(IntPtr hWnd1, IntPtr hWnd2, string lpsz1, string lpsz2);
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, IntPtr lParam);
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, uint msg, int wParam, IntPtr lParam);
public enum Message : int
{
WM_MOUSEMOVE = 0x200,
WM_LBUTTONDOWN = 0x201, //Left mousebutton down
WM_LBUTTONUP = 0x202, //Left mousebutton up
WM_LBUTTONDBLCLK = 0x203, //Left mousebutton doubleclick
WM_RBUTTONDOWN = 0x204, //Right mousebutton down
WM_RBUTTONUP = 0x205, //Right mousebutton up
WM_RBUTTONDBLCLK = 0x206, //Right mousebutton doubleclick
WM_KEYDOWN = 0x100, //Key down
WM_KEYUP = 0x101, //Key up
WM_SYSKEYDOWN = 0x104,
WM_SYSKEYUP = 0x105,
WM_CHAR = 0x102, //char
WM_COMMAND = 0x111
}
public enum VirtualKey : int
{
VK_RETURN = 0x0D,
VK_F1 = 0x70,
VK_F2 = 0x71,
VK_F3 = 0x72,
VK_F4 = 0x73,
VK_F5 = 0x74,
VK_F6 = 0x75,
VK_F7 = 0x76,
VK_F8 = 0x77,
VK_F9 = 0x78,
VK_F10 = 0x79,
VK_F11 = 0x7A,
VK_F12 = 0x7B
}
public static IntPtr GetWindowByTitleContains(string title)
{
IntPtr hWnd = IntPtr.Zero;
foreach (Process proc in Process.GetProcesses())
{
if (proc.MainWindowTitle.Contains(title))
{
hWnd = proc.MainWindowHandle;
break;
}
}
return hWnd;
}
}
}

View File

@ -0,0 +1,17 @@
# 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

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