Compare commits

...

387 Commits

Author SHA1 Message Date
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
86 changed files with 8398 additions and 1109 deletions

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

8
.gitignore vendored
View File

@ -103,13 +103,13 @@ dist
# TernJS port file
.tern-port
# user defined assets
# user private assets
bin
data/chatgpt-apikey.txt
data/anthropic-apikey.txt
data/groq-apikey.txt
data/*-apikey.txt
data/*.nomedia.txt
app/assets/img/_templates
app/assets/img/_captured
settings.ini
defaultService.js
lib/*.private.js
data/python313.zip

228
README.md
View File

@ -3,101 +3,82 @@
[![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/8278298336)
[![Anthropic available](https://img.shields.io/badge/Anthropic-000000?logo=Anthropic&logoColor=white)](https://catswords-oss.rdbl.io/5719744820/8278298336)
[![slideshare.net available](https://img.shields.io/badge/SlideShare-black?logo=slideshare)](https://www.slideshare.net/slideshow/welsonjs-2023/263181443)
[![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.
![(This is a cover image) Windows in 1999](https://ics.catswords.net/cover.png)
![A Cover Image: Windows in 1999](https://ics.catswords.net/cover.png)
Now, You can build an Windows desktop app with JavaScript, TypeScript, CoffeeScript, ReScript, and HTML/CSS on Windows built-in ECMAScript engine.
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)*** + [Your contribution](https://github.com/sponsors/gnh1201)
WelsonJS = ***W***indows + ***El***ectr***on***-like + ***Javascript(JS)*** + :heart:[Contributions](https://github.com/sponsors/gnh1201)
Dual license notice: The default license for this project is GPL 3.0. However, if the GPL 3.0 license is not compatible with Microsoft products, it is subject to the MS-RL license.
* :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)
- <img src="https://ics.catswords.net/logo_oss.gif" height="32" alt=""/> Open Software Portal, Korea National Industry Promotion Agency - Awarded Prize
- <img src="https://ics.catswords.net/signpath_logo.png" height="32" alt=""/> Free code signing provided by [SignPath.io](https://signpath.io), certificate by [SignPath Foundation](https://signpath.org/)
- :zap: [Integrations](https://catswords-oss.rdbl.io/5719744820/8278298336) ([ScrapeOps](https://scrapeops.io?fpr=namhyeon75), [SearchApi](https://www.searchapi.io/?via=namhyeon), ...)
* :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
![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
- 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 require additional software installation.
- ES5(ECMAScript 5), XML, JSON, YAML compatibility
- [github.com/zloirock/core-js](https://github.com/zloirock/core-js)
- [github.com/douglascrockford/JSON-js](https://github.com/douglascrockford/JSON-js) (aka. JSON2.js)
- [github.com/nodeca/js-yaml](https://github.com/nodeca/js-yaml)
- HTML5, CSS3 compatibility
- [github.com/aFarkas/html5shiv](https://github.com/aFarkas/html5shiv)
- [github.com/parndt/jquery-html5-placeholder-shim](https://github.com/parndt/jquery-html5-placeholder-shim)
- [github.com/scottjehl/Respond](https://github.com/scottjehl/Respond)
- [github.com/keithclark/selectivizr](https://github.com/keithclark/selectivizr)
- [github.com/arv/ExplorerCanvas](https://github.com/arv/ExplorerCanvas)
- [github.com/Modernizr/Modernizr](https://github.com/Modernizr/Modernizr)
- CSS Frameworks
- [github.com/jslegers/cascadeframework](https://github.com/jslegers/cascadeframework)
- [github.com/golden-layout/golden-layout](https://github.com/golden-layout/golden-layout)
- WYSIWYG HTML Editor
- [github.com/summernote/summernote](https://github.com/summernote/summernote)
- Included libraries
- [jQuery](https://jquery.com/)
- [jQuery UI](https://jqueryui.com/)
- [github.com/kamranahmedse/jquery-toast-plugin](https://github.com/kamranahmedse/jquery-toast-plugin) - Highly customizable jquery plugin to show toast messages
- [github.com/hiddentao/squel](https://github.com/hiddentao/squel) - SQL query string builder for Javascript
- [github.com/BorisMoore/jsrender](https://github.com/BorisMoore/jsrender) - A lightweight, powerful and highly extensible templating engine. In the browser or on Node.js, with or without jQuery.
- [github.com/mihaifm/linq](https://github.com/mihaifm/linq) - LINQ for JavaScript
- [github.com/pegjs/pegjs](https://github.com/pegjs/pegjs) - PEG.js: Parser generator for JavaScript
- [github.com/numbers/numbers.js](https://github.com/numbers/numbers.js) - Advanced Mathematics Library for Node.js and JavaScript
- [module.exports](https://nodejs.org/api/modules.html#moduleexports), CommonJS, UMD compatibility
- [NPM](https://www.npmjs.com/) compatibility
- [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/) support
- [ADB(Android Debug Bridge)](https://source.android.com/docs/setup/build/adb) support
- RPC(Remote Procedure Call) protocol support
- [gRPC](https://grpc.io/)
- [JSON-RPC 2.0](https://www.jsonrpc.org/specification)
* 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 modules
- lib/std (Standard library)
- lib/system (System interface)
- lib/base64 (BASE64 encode and decode)
- lib/file (File I/O interface)
- lib/http (HTTP/HTTPS client with [XHR(MSXML)](https://developer.mozilla.org/docs/Glossary/XMLHttpRequest), [cURL](https://curl.se/), [BITS](https://en.m.wikipedia.org/w/index.php?title=Background_Intelligent_Transfer_Service), [CERT](https://github.com/MicrosoftDocs/windowsserverdocs/blob/main/WindowsServerDocs/administration/windows-commands/certutil.md), [Proxy/SEO/SERP](https://catswords-oss.rdbl.io/5719744820/1706431912))
- lib/registry (Windows Registry interface)
- lib/security (Windows Security Policy interface)
- lib/shell (Windows Shell (Command Prompt) interface)
- lib/powershell (Windows Powershell interface)
- lib/service (Windows Service interface)
- lib/browser (Modern web compatibility layer)
- lib/uri (URI scheme interface)
- lib/winlibs (Windows DLL(Dynamic-link library) interface)
- lib/autohotkey ([AutoHotkey](https://www.autohotkey.com/) interface)
- lib/autoit ([AutoIt3/AutoItX](https://www.autoitscript.com/) interface)
- lib/msoffice (Microsoft Office (e.g. Excel, PowerPoint, Word) interface)
- lib/gtk (GTK-server and GladeXML supported GUI interface)
- lib/chrome ([Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/) based Chrome/Chromium web browser testing interface)
- lib/pipe-ipc (PIPE (e.g., File IO, Standard IO) based IPC(Inter-Process Communication) implementation)
- [WelsonJS.Toolkit](https://catswords-oss.rdbl.io/5719744820/0811015590) (DLL/COM component with .NET 2.0, For all Windows based systems)
- User prompt methods (e.g., alert, confirm) implementation
- Useful tools to control the windows and window handle (find, attach, trigger events. e.g., Virtual Human Interface
- Cryptography ([ISO/IEC 18033-3:2010](https://www.iso.org/standard/54531.html) aka. [HIGHT](https://seed.kisa.or.kr/kisa/algorithm/EgovHightInfo.do))
- [Named Shared Memory](https://learn.microsoft.com/en-us/windows/win32/memory/creating-named-shared-memory) based IPC(Inter-Process Communication) implementation [#](https://qiita.com/gnh1201/items/4e70dccdb7adacf0ace5)
- [NuGet package](https://www.nuget.org/packages/WelsonJS.Toolkit) available
- [WelsonJS.Service](https://catswords-oss.rdbl.io/5719744820/0811015590) (Windows Service Application, For recent Windows based systems)
- Write a Windows Service Application with JavaScript
- [File Event Monitor](https://catswords-oss.rdbl.io/5719744820/6159022056): Trace file creation, network connections, and registry modifications.
- [Screen Time Feature](https://catswords-oss.rdbl.io/5719744820/8803957194): Find an image position on the computer screens or windows.
- [WelsonJS.Launcher](https://catswords-oss.rdbl.io/5719744820/4131485779) (Launcher Application, For recent Windows based systems)
- This is a launcher app designed to easily distribute WelsonJS application packages (based on ZIP compression files).
- [ChatGPT](https://openai.com/index/chatgpt/) or [Anthropic/Claude](https://claude.ai/) integration
- Everything you can imagine.
## Make your own `sayhello` example
## Quick start
### 1. Write a file `lib/sayhello.js`
```js
@ -108,8 +89,8 @@ function say() {
exports.say = say;
exports.VERSIONINFO = "SayHello Library (sayhello.js) version 0.1";
exports.AUTHOR = "abuse@catswords.net"; // e.g. YOUR EMAIL ADDRESS
exports.VERSIONINFO = "SayHello (sayhello.js) version 0.1";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;
```
@ -128,9 +109,9 @@ function main() {
exports.main = main;
```
### 3. Execute file on the command prompt
### 3. Execute script on the console
```cmd
C:\Users\knh94\Documents\GitHub\welsonjs> cscript app.js sayhello
C:\Users\JohnDoe\Documents\GitHub\welsonjs> cscript app.js sayhello
calling say()
hello
ended say()
@ -139,9 +120,9 @@ ended say()
## 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). Information needed to create the setup file (the `setup.iss` file) is already included.
- **Copy all directories and files**: This is the simplest and most straightforward method.
* **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) GUI environment](https://ics.catswords.net/screenshot.png)
@ -156,44 +137,45 @@ The WelsonJS framework suggests the following application release methods:
![(Screenshot 6) The Launcher for WelsonJS Application Packages](https://ics.catswords.net/screenshot6.png)
## Thanks to
- :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) - [Mentioned](https://www.facebook.com/javascript4u/posts/build-a-windows-desktop-apps-with-javascript-html-and-cssmorioh-javascript-html-/1484014618472735/)
- :eyes: morioh.com - [Mentioned](https://morioh.com/a/23c427a82bf1/build-a-windows-desktop-apps-with-javascript-html-and-css)
- :eyes: CSDN - Mentioned
- :eyes: Qiita - Knowledge-base about WSH environment
- :eyes: 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 an inter-language IPC implementation devised by an unidentified developer.
- :eyes: Fediverse - Mentioned
- :eyes: Hacker News - [Mentioned](https://news.ycombinator.com/item?id=41316782)
- :eyes: WebToolsWeekly - [Mentioned](https://webtoolsweekly.com/archives/issue-585/)
- :eyes: GeekNews - [Mentioned](https://news.hada.io/weekly/202441) in GeekNews Weekly (2024-09-30 ~ 2024-10-06)
- :eyes: daily.dev - [Mentioned](https://app.daily.dev/posts/js-libraries-svg-tools-json-databases-8quregz3a)
- :eyes: PitchHut - [Mentioned](https://www.pitchhut.com/project/proj_Ya136OLSW5at)
![(Screenshot 7) Microsoft Monaco Editor on WelsonJS Launcher](https://ics.catswords.net/screenshot7.png)
## Related links
- [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
- FOSSA report [HTML](https://ics.catswords.net/fossa_report.html) [CSV](https://ics.catswords.net/fossa_report.csv) [TXT](https://ics.catswords.net/fossa_report.txt)
- [License attributions of a stock images](https://policy.catswords.social/stock_images.html)
## 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](https://github.com/gnh1201/welsonjs/security)
- abuse@catswords.net
- 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](https://teams.live.com/l/community/FEACHncAhq8ldnojAI)
- [Join Catswords OSS #welsonjs on Discord](https://discord.gg/XKG5CjtXEj)
* [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

@ -9,17 +9,17 @@ This repository contains information on accessing Windows APIs and functions in
## Known Use Cases
WelsonJS is typically used for the following purposes:
* 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.
* 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.
## 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.
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.
## Guidelines
@ -41,16 +41,23 @@ WelsonJS is a project inspired by the requirements of a cloud service provider t
## 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) (CERN/OpenAIRE Zenodo)
- ["A0562"](https://www.oss.kr/dev_competition_activities/show/544723e6-850a-4956-9194-79640420c19a)(2023) (2023 Open-source Development Contest, NIPA National IT Industry Promotion Agency, Republic of Korea)
- "C-2021-000237"(2021) (Copyright Registration Online System, Korea Copyright Commission, Republic of Korea)
- "Codename Macadamia"(2020) (Heavy industry specialized CSP in the Republic of Korea)
* 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 discover any instances of this project being misused, please report them.
## Report abuse
* [GitHub Security Advisories](https://github.com/gnh1201/welsonjs/security)
* [abuse@catswords.net](mailto:abuse@catswords.net)
- [GitHub Security Advisories](https://github.com/gnh1201/welsonjs/security)
- abuse@catswords.net
- ActivityPub [@catswords_oss@catswords.social](https://catswords.social/@catswords_oss)
- XMPP [catswords@conference.xmpp.catswords.net](xmpp:catswords@conference.xmpp.catswords.net?join)
- [Join Catswords on Microsoft Teams](https://teams.live.com/l/community/FEACHncAhq8ldnojAI)
## 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.

View File

@ -28,11 +28,11 @@
/// </summary>
private void InitializeComponent()
{
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.listView1 = new System.Windows.Forms.ListView();
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.groupBox2 = new System.Windows.Forms.GroupBox();
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();
@ -41,36 +41,36 @@
this.textSetName = new System.Windows.Forms.TextBox();
this.labelSetValue = new System.Windows.Forms.Label();
this.labelSetName = new System.Windows.Forms.Label();
this.groupBox3 = new System.Windows.Forms.GroupBox();
this.gbImportAndExport = new System.Windows.Forms.GroupBox();
this.btnExport = new System.Windows.Forms.Button();
this.btnImport = new System.Windows.Forms.Button();
this.groupBox1.SuspendLayout();
this.groupBox2.SuspendLayout();
this.groupBox3.SuspendLayout();
this.gbUserDefinedVariables.SuspendLayout();
this.gbUpdateUserDefinedVariable.SuspendLayout();
this.gbImportAndExport.SuspendLayout();
this.SuspendLayout();
//
// groupBox1
// gbUserDefinedVariables
//
this.groupBox1.Controls.Add(this.listView1);
this.groupBox1.Location = new System.Drawing.Point(12, 12);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(419, 170);
this.groupBox1.TabIndex = 0;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "User-defined variables";
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";
//
// listView1
// lvUserDefinedVariables
//
this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.lvUserDefinedVariables.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.columnHeader1,
this.columnHeader2});
this.listView1.HideSelection = false;
this.listView1.Location = new System.Drawing.Point(16, 26);
this.listView1.Name = "listView1";
this.listView1.Size = new System.Drawing.Size(386, 129);
this.listView1.TabIndex = 0;
this.listView1.UseCompatibleStateImageBehavior = false;
this.listView1.SelectedIndexChanged += new System.EventHandler(this.ListView1_SelectedIndexChanged);
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
//
@ -80,22 +80,22 @@
//
this.columnHeader2.Text = "Value";
//
// groupBox2
// gbUpdateUserDefinedVariable
//
this.groupBox2.Controls.Add(this.checkDeleteVariable);
this.groupBox2.Controls.Add(this.btnOk);
this.groupBox2.Controls.Add(this.btnOpenFile);
this.groupBox2.Controls.Add(this.btnOpenDirectory);
this.groupBox2.Controls.Add(this.textSetValue);
this.groupBox2.Controls.Add(this.textSetName);
this.groupBox2.Controls.Add(this.labelSetValue);
this.groupBox2.Controls.Add(this.labelSetName);
this.groupBox2.Location = new System.Drawing.Point(12, 188);
this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(419, 229);
this.groupBox2.TabIndex = 1;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "Update the user-defined variable";
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
//
@ -125,9 +125,12 @@
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);
//
@ -137,9 +140,12 @@
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);
//
@ -175,16 +181,16 @@
this.labelSetName.TabIndex = 0;
this.labelSetName.Text = "Set name:";
//
// groupBox3
// gbImportAndExport
//
this.groupBox3.Controls.Add(this.btnExport);
this.groupBox3.Controls.Add(this.btnImport);
this.groupBox3.Location = new System.Drawing.Point(12, 423);
this.groupBox3.Name = "groupBox3";
this.groupBox3.Size = new System.Drawing.Size(419, 89);
this.groupBox3.TabIndex = 2;
this.groupBox3.TabStop = false;
this.groupBox3.Text = "Import and export";
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
//
@ -192,6 +198,7 @@
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";
@ -204,6 +211,7 @@
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";
@ -215,26 +223,26 @@
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.groupBox3);
this.Controls.Add(this.groupBox2);
this.Controls.Add(this.groupBox1);
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.groupBox1.ResumeLayout(false);
this.groupBox2.ResumeLayout(false);
this.groupBox2.PerformLayout();
this.groupBox3.ResumeLayout(false);
this.gbUserDefinedVariables.ResumeLayout(false);
this.gbUpdateUserDefinedVariable.ResumeLayout(false);
this.gbUpdateUserDefinedVariable.PerformLayout();
this.gbImportAndExport.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.GroupBox groupBox2;
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;
@ -243,10 +251,10 @@
private System.Windows.Forms.Button btnOpenFile;
private System.Windows.Forms.Button btnOpenDirectory;
private System.Windows.Forms.CheckBox checkDeleteVariable;
private System.Windows.Forms.ListView listView1;
private System.Windows.Forms.ListView lvUserDefinedVariables;
private System.Windows.Forms.ColumnHeader columnHeader1;
private System.Windows.Forms.ColumnHeader columnHeader2;
private System.Windows.Forms.GroupBox groupBox3;
private System.Windows.Forms.GroupBox gbImportAndExport;
private System.Windows.Forms.Button btnImport;
private System.Windows.Forms.Button btnExport;
}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Forms;
namespace WelsonJS.Launcher
@ -9,24 +10,27 @@ namespace WelsonJS.Launcher
{
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 in the temporary folder
tempFilePath = Path.Combine(Path.GetTempPath(), "welsonjs_default.env");
// Set the variable file path
tempFilePath = Path.Combine(Program.GetAppDataPath(), "welsonjs_default.env");
LoadUserVariables(); // Load variables
}
// Initialize ListView
private void InitializeListView()
{
listView1.View = View.Details;
listView1.FullRowSelect = true;
listView1.Columns[0].Width = 150;
listView1.Columns[1].Width = 220;
listView1.SelectedIndexChanged += ListView1_SelectedIndexChanged;
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
@ -84,21 +88,21 @@ namespace WelsonJS.Launcher
// Update ListView with current variables
private void UpdateListView()
{
listView1.Items.Clear();
lvUserDefinedVariables.Items.Clear();
foreach (var variable in userVariables)
{
var item = new ListViewItem(variable.Key);
item.SubItems.Add(variable.Value);
listView1.Items.Add(item);
lvUserDefinedVariables.Items.Add(item);
}
}
// Handle ListView selection change
private void ListView1_SelectedIndexChanged(object sender, EventArgs e)
private void lvUserDefinedVariables_SelectedIndexChanged(object sender, EventArgs e)
{
if (listView1.SelectedItems.Count > 0)
if (lvUserDefinedVariables.SelectedItems.Count > 0)
{
var selectedItem = listView1.SelectedItems[0];
var selectedItem = lvUserDefinedVariables.SelectedItems[0];
textSetName.Text = selectedItem.Text;
textSetValue.Text = selectedItem.SubItems[1].Text;
checkDeleteVariable.Checked = false;
@ -164,7 +168,7 @@ namespace WelsonJS.Launcher
}
// Write lines to the file
File.WriteAllLines(tempFilePath, lines);
File.WriteAllLines(tempFilePath, lines, defaultEncoding);
}
catch (Exception ex)
{
@ -183,68 +187,74 @@ namespace WelsonJS.Launcher
// Handle "Open Directory" button click
private void btnOpenDirectory_Click(object sender, EventArgs e)
{
var folderDialog = new FolderBrowserDialog();
if (folderDialog.ShowDialog() == DialogResult.OK)
using (var folderDialog = new FolderBrowserDialog())
{
textSetValue.Text = folderDialog.SelectedPath;
if (folderDialog.ShowDialog() == DialogResult.OK)
{
textSetValue.Text = folderDialog.SelectedPath;
}
}
}
// Handle "Open File" button click
private void btnOpenFile_Click(object sender, EventArgs e)
{
var fileDialog = new OpenFileDialog();
if (fileDialog.ShowDialog() == DialogResult.OK)
using (var fileDialog = new OpenFileDialog())
{
textSetName.Text = Path.GetFileName(fileDialog.FileName);
textSetValue.Text = fileDialog.FileName;
if (fileDialog.ShowDialog() == DialogResult.OK)
{
textSetName.Text = Path.GetFileName(fileDialog.FileName);
textSetValue.Text = fileDialog.FileName;
}
}
}
private void btnImport_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "Env files (*.env)|*.env|All files (*.*)|*.*";
if (openFileDialog.ShowDialog() == DialogResult.OK)
using (var openFileDialog = new OpenFileDialog())
{
try
openFileDialog.Filter = "Env files (*.env)|*.env|All files (*.*)|*.*";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
// Load variables from the selected file
string filePath = openFileDialog.FileName;
string[] lines = File.ReadAllLines(filePath);
foreach (string line in lines)
try
{
// Skip empty lines
if (string.IsNullOrWhiteSpace(line)) continue;
// Load variables from the selected file
string filePath = openFileDialog.FileName;
string[] lines = File.ReadAllLines(filePath, defaultEncoding);
int indexOfEquals = line.IndexOf('=');
if (indexOfEquals != -1)
foreach (string line in lines)
{
string key = line.Substring(0, indexOfEquals).Trim();
string value = line.Substring(indexOfEquals + 1).Trim();
// Skip empty lines
if (string.IsNullOrWhiteSpace(line)) continue;
// Remove surrounding quotes if present
if (value.StartsWith("\"") && value.EndsWith("\""))
int indexOfEquals = line.IndexOf('=');
if (indexOfEquals != -1)
{
value = value.Substring(1, value.Length - 2);
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;
}
// 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);
// 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);
}
}
}
}
@ -273,7 +283,7 @@ namespace WelsonJS.Launcher
lines.Add($"{variable.Key}={value}");
}
File.WriteAllLines(filePath, lines);
File.WriteAllLines(filePath, lines, defaultEncoding);
}
catch (Exception ex)
{

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

@ -28,42 +28,54 @@
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
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.checkBox1 = new System.Windows.Forms.CheckBox();
this.textBox1 = new System.Windows.Forms.TextBox();
this.checkBox2 = new System.Windows.Forms.CheckBox();
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();
//
// button1
// btnRunFromZipFile
//
this.button1.Image = global::WelsonJS.Launcher.Properties.Resources.icon_zip_128;
this.button1.Location = new System.Drawing.Point(24, 67);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(200, 200);
this.button1.TabIndex = 0;
this.button1.Text = "From ZIP file...";
this.button1.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
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);
//
// button2
// btnRunFromExternalLink
//
this.button2.Image = global::WelsonJS.Launcher.Properties.Resources.icon_link_128;
this.button2.Location = new System.Drawing.Point(230, 67);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(200, 200);
this.button2.TabIndex = 1;
this.button2.Text = "From external link...";
this.button2.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.button2_Click);
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
//
@ -85,34 +97,34 @@
this.linkLabel1.Text = "https://github.com/gnh1201/welsonjs";
this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
//
// checkBox1
// cbUseSpecificScript
//
this.checkBox1.AutoSize = true;
this.checkBox1.Location = new System.Drawing.Point(26, 281);
this.checkBox1.Name = "checkBox1";
this.checkBox1.Size = new System.Drawing.Size(184, 16);
this.checkBox1.TabIndex = 4;
this.checkBox1.Text = "I want to use specific script ";
this.checkBox1.UseVisualStyleBackColor = true;
this.checkBox1.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged);
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);
//
// textBox1
// txtUseSpecificScript
//
this.textBox1.Enabled = false;
this.textBox1.Location = new System.Drawing.Point(214, 278);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(110, 21);
this.textBox1.TabIndex = 5;
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;
//
// checkBox2
// cbInteractiveServiceApp
//
this.checkBox2.AutoSize = true;
this.checkBox2.Location = new System.Drawing.Point(26, 305);
this.checkBox2.Name = "checkBox2";
this.checkBox2.Size = new System.Drawing.Size(254, 16);
this.checkBox2.TabIndex = 6;
this.checkBox2.Text = "This is an Interactive Service Application";
this.checkBox2.UseVisualStyleBackColor = true;
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
//
@ -127,7 +139,12 @@
// settingsToolStripMenuItem
//
this.settingsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.userdefinedVariablesToolStripMenuItem});
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";
@ -135,31 +152,101 @@
// userdefinedVariablesToolStripMenuItem
//
this.userdefinedVariablesToolStripMenuItem.Name = "userdefinedVariablesToolStripMenuItem";
this.userdefinedVariablesToolStripMenuItem.Size = new System.Drawing.Size(192, 22);
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.checkBox2);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.checkBox1);
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.button2);
this.Controls.Add(this.button1);
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.Launcher";
this.Text = "WelsonJS Application Launcher";
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();
this.contextMenuStrip1.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
@ -167,16 +254,26 @@
#endregion
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
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 checkBox1;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.CheckBox checkBox2;
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

@ -2,64 +2,113 @@
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Security.Principal;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Linq;
namespace WelsonJS.Launcher
{
public partial class MainForm : Form
{
private string workingDirectory;
private string instanceName;
private string instanceId;
private string entryFileName;
private string scriptName;
public MainForm()
{
entryFileName = "bootstrap.bat";
InitializeComponent();
entryFileName = "bootstrap.bat";
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.";
button1.Enabled = true;
button2.Enabled = true;
checkBox1.Enabled = true;
if (checkBox1.Checked)
btnRunFromZipFile.Enabled = true;
btnRunFromExternalLink.Enabled = true;
cbUseSpecificScript.Enabled = true;
cbInteractiveServiceApp.Enabled = true;
if (cbUseSpecificScript.Checked)
{
textBox1.Enabled = true;
txtUseSpecificScript.Enabled = true;
}
}
private void DisableUI()
{
label1.Text = "Please wait...";
button1.Enabled = false;
button2.Enabled = false;
checkBox1.Enabled = false;
textBox1.Enabled = false;
btnRunFromZipFile.Enabled = false;
btnRunFromExternalLink.Enabled = false;
cbUseSpecificScript.Enabled = false;
cbInteractiveServiceApp.Enabled = false;
txtUseSpecificScript.Enabled = false;
}
private void button2_Click(object sender, EventArgs e)
private void SafeInvoke(Action action)
{
MessageBox.Show("Comming soon...!");
}
private void button1_Click(object sender, EventArgs e)
{
string filePath = OpenFileDialog();
if (filePath != null)
if (InvokeRequired)
{
string fileExtension = Path.GetExtension(filePath);
if (fileExtension != ".zip")
{
MessageBox.Show("It doesn't seems to a ZIP file.");
}
else
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);
}
}
@ -67,9 +116,9 @@ namespace WelsonJS.Launcher
private void ExtractAndRun(string filePath)
{
instanceName = Guid.NewGuid().ToString();
workingDirectory = Path.Combine(Path.GetTempPath(), instanceName);
scriptName = textBox1.Text;
instanceId = Guid.NewGuid().ToString();
workingDirectory = Program.GetWorkingDirectory(instanceId);
scriptName = txtUseSpecificScript.Text;
Task.Run(() =>
{
@ -84,19 +133,25 @@ namespace WelsonJS.Launcher
// try to extact ZIP file
ZipFile.ExtractToDirectory(filePath, workingDirectory);
// If it is created the sub-directory
workingDirectory = GetFinalDirectory(workingDirectory);
// record the first deploy time
RecordFirstDeployTime(workingDirectory);
// follow the sub-directory
workingDirectory = Program.GetWorkingDirectory(instanceId, true);
// Run the appliction
RunCommandPrompt();
Program.RunCommandPrompt(workingDirectory, entryFileName, scriptName, cbUseSpecificScript.Checked, cbInteractiveServiceApp.Checked);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
SafeInvoke(() =>
{
MessageBox.Show("Error: " + ex.Message);
});
}
// Enable UI
label1.Invoke((MethodInvoker)delegate {
SafeInvoke(() => {
EnableUI();
});
});
@ -104,111 +159,117 @@ namespace WelsonJS.Launcher
DisableUI();
}
private void RunCommandPrompt()
private void RecordFirstDeployTime(string directory)
{
bool isConsoleApplication = checkBox1.Checked;
bool isInteractiveServiceAapplication = checkBox2.Checked;
try
{
string filePath = Path.Combine(directory, ".welsonjs_first_deploy_time");
string text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
if (!isConsoleApplication)
{
if (!File.Exists(Path.Combine(workingDirectory, entryFileName)))
{
throw new Exception("Not Found: " + entryFileName);
}
File.WriteAllText(filePath, text);
}
else
catch (Exception ex)
{
if (!Directory.EnumerateFiles(workingDirectory, scriptName + ".*").Any())
{
throw new Exception("Not found matches file: " + scriptName);
}
throw new Exception($"Failed to record first deploy time: {ex.Message}");
}
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();
}
private string OpenFileDialog()
private bool IsInAdministrator()
{
string filePath = null;
using (OpenFileDialog fileDialog = new OpenFileDialog())
try
{
if (fileDialog.ShowDialog() == DialogResult.OK)
{
// Get the path of specified file
filePath = fileDialog.FileName;
}
WindowsPrincipal wp = new WindowsPrincipal(WindowsIdentity.GetCurrent());
return wp.IsInRole(WindowsBuiltInRole.Administrator);
}
catch
{
return false;
}
return filePath;
}
private string GetFinalDirectory(string path)
private void cbUseSpecificScript_CheckedChanged(object sender, EventArgs e)
{
string[] directories = Directory.GetDirectories(path);
while (directories.Length == 1)
{
path = directories[0];
directories = Directory.GetDirectories(path);
}
return path;
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
textBox1.Enabled = checkBox1.Checked;
txtUseSpecificScript.Enabled = cbUseSpecificScript.Checked;
}
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
Process.Start("https://github.com/gnh1201/welsonjs");
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

@ -120,4 +120,10 @@
<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

@ -1,20 +1,191 @@
using System;
using System.Collections.Generic;
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
{
/// <summary>
/// 해당 애플리케이션의 주 진입점입니다.
/// </summary>
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

@ -6,11 +6,11 @@ using System.Runtime.InteropServices;
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
// 이러한 특성 값을 변경하세요.
[assembly: AssemblyTitle("WelsonJS.Launcher")]
[assembly: AssemblyDescription("Launcher for WelsonJS Application Package")]
[assembly: AssemblyDescription("Launcher for WelsonJS Application Packages")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Catswords")]
[assembly: AssemblyProduct("WelsonJS")]
[assembly: AssemblyCopyright("Catswords OSS, Opensource licensed under GPLv3")]
[assembly: AssemblyCopyright("Catswords OSS, GPLv3 or Ms-RL")]
[assembly: AssemblyTrademark("WelsonJS")]
[assembly: AssemblyCulture("")]
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
// 기본값으로 할 수 있습니다.
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.2.7.49")]
[assembly: AssemblyFileVersion("0.2.7.49")]
[assembly: AssemblyVersion("0.2.7.54")]
[assembly: AssemblyFileVersion("0.2.7.54")]

View File

@ -60,6 +60,105 @@ namespace WelsonJS.Launcher.Properties {
}
}
/// <summary>
/// https://ajax.aspnetcdn.com/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string AspNetCdnPrefix {
get {
return ResourceManager.GetString("AspNetCdnPrefix", resourceCulture);
}
}
/// <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/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string BlobStoragePrefix {
get {
return ResourceManager.GetString("BlobStoragePrefix", resourceCulture);
}
}
/// <summary>
/// https://cdnjs.cloudflare.com/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string CdnJsPrefix {
get {
return ResourceManager.GetString("CdnJsPrefix", 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>
/// https://esm.run/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string EsmRunPrefix {
get {
return ResourceManager.GetString("EsmRunPrefix", resourceCulture);
}
}
/// <summary>
/// https://esm.sh/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string EsmShPrefix {
get {
return ResourceManager.GetString("EsmShPrefix", resourceCulture);
}
}
/// <summary>
/// (아이콘)과(와) 유사한 System.Drawing.Icon 형식의 지역화된 리소스를 찾습니다.
/// </summary>
@ -70,6 +169,15 @@ namespace WelsonJS.Launcher.Properties {
}
}
/// <summary>
/// https://ajax.googleapis.com/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string GoogleApisPrefix {
get {
return ResourceManager.GetString("GoogleApisPrefix", resourceCulture);
}
}
/// <summary>
/// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다.
/// </summary>
@ -80,6 +188,16 @@ namespace WelsonJS.Launcher.Properties {
}
}
/// <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>
@ -130,6 +248,16 @@ namespace WelsonJS.Launcher.Properties {
}
}
/// <summary>
/// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다.
/// </summary>
internal static System.Drawing.Bitmap icon_start_32 {
get {
object obj = ResourceManager.GetObject("icon_start_32", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// System.Drawing.Bitmap 형식의 지역화된 리소스를 찾습니다.
/// </summary>
@ -139,5 +267,104 @@ namespace WelsonJS.Launcher.Properties {
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// https://code.jquery.com/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string JqueryCdnPrefix {
get {
return ResourceManager.GetString("JqueryCdnPrefix", resourceCulture);
}
}
/// <summary>
/// https://cdn.jsdelivr.net/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string JsDeliverPrefix {
get {
return ResourceManager.GetString("JsDeliverPrefix", resourceCulture);
}
}
/// <summary>
/// https://polyfill-fastly.io/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string PolyfillPrefix {
get {
return ResourceManager.GetString("PolyfillPrefix", resourceCulture);
}
}
/// <summary>
/// https://raw.githubusercontent.com/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string RawGitHubPrefix {
get {
return ResourceManager.GetString("RawGitHubPrefix", resourceCulture);
}
}
/// <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>
/// https://www.skypack.dev/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string SkypackPrefix {
get {
return ResourceManager.GetString("SkypackPrefix", resourceCulture);
}
}
/// <summary>
/// https://unpkg.com/과(와) 유사한 지역화된 문자열을 찾습니다.
/// </summary>
internal static string UnpkgPrefix {
get {
return ResourceManager.GetString("UnpkgPrefix", 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

@ -142,4 +142,79 @@
<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="CdnJsPrefix" xml:space="preserve">
<value>https://cdnjs.cloudflare.com/</value>
</data>
<data name="EsmRunPrefix" xml:space="preserve">
<value>https://esm.run/</value>
</data>
<data name="EsmShPrefix" xml:space="preserve">
<value>https://esm.sh/</value>
</data>
<data name="JqueryCdnPrefix" xml:space="preserve">
<value>https://code.jquery.com/</value>
</data>
<data name="JsDeliverPrefix" xml:space="preserve">
<value>https://cdn.jsdelivr.net/</value>
</data>
<data name="SkypackPrefix" xml:space="preserve">
<value>https://www.skypack.dev/</value>
</data>
<data name="UnpkgPrefix" xml:space="preserve">
<value>https://unpkg.com/</value>
</data>
<data name="AspNetCdnPrefix" xml:space="preserve">
<value>https://ajax.aspnetcdn.com/</value>
</data>
<data name="GoogleApisPrefix" xml:space="preserve">
<value>https://ajax.googleapis.com/</value>
</data>
<data name="PolyfillPrefix" xml:space="preserve">
<value>https://polyfill-fastly.io/</value>
</data>
<data name="RawGitHubPrefix" xml:space="preserve">
<value>https://raw.githubusercontent.com/</value>
</data>
</root>

View File

@ -0,0 +1,446 @@
// 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;
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 readonly HttpClient _httpClient = new HttpClient();
private static readonly string _defaultMimeType = "application/octet-stream";
private static readonly Regex _nodePackageRegex = new Regex(@"^[^/@]+@[^/]+/", RegexOptions.Compiled);
private static readonly List<string[]> CDN_PREFIXES = new List<string[]> {
new[] { "ajax/libs/" },
new[] { "npm/", "gh/", "wp/" },
new[] { "jquery/" },
new[] { "polyfill/" },
new[] { "ajax/" }, // https://learn.microsoft.com/en-us/aspnet/ajax/cdn/overview
new[] { "raw/gh/"}
};
private enum CDN_TYPES: int
{
Cloudflare = 0,
JsDeliver = 1,
Jquery = 2,
Polyfill = 3,
Microsoft = 4,
GitHub = 5
};
public ResourceServer(string prefix, string resourceName)
{
_prefix = prefix;
_listener = new HttpListener();
_listener.Prefixes.Add(prefix);
_resourceName = resourceName;
_httpClient.Timeout = TimeSpan.FromSeconds(30);
// 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 CDN sources
if (await TryServeFromCdn(context, path))
{
return true;
}
}
return false;
}
private async Task<bool> TryServeFromCdn(HttpListenerContext context, string path)
{
bool isNodePackageExpression = _nodePackageRegex.IsMatch(path);
bool isPrefixMatched(CDN_TYPES type)
{
if (CDN_PREFIXES[(int)type].Any(prefix => path.StartsWith(prefix)))
{
return true;
}
return false;
}
var sources = new (bool isMatch, string configKey, Func<string, string> transform)[]
{
(isPrefixMatched(CDN_TYPES.Cloudflare), "CdnJsPrefix", p => p), // Libraries from Cloudflare
(isPrefixMatched(CDN_TYPES.Cloudflare), "GoogleApisPrefix", p => p), // Libraries from Google
(isNodePackageExpression, "UnpkgPrefix", p => p),
(isNodePackageExpression, "SkypackPrefix", p => p),
(isNodePackageExpression, "EsmShPrefix", p => p),
(isNodePackageExpression, "EsmRunPrefix", p => p),
(isPrefixMatched(CDN_TYPES.JsDeliver), "JsDeliverPrefix", p => p),
(isPrefixMatched(CDN_TYPES.Jquery), "JqueryCdnPrefix", p => p.Substring("jquery/".Length)),
(isPrefixMatched(CDN_TYPES.Polyfill), "CdnJsPrefix", p => p), // polyfill.js from Cloudflare
(isPrefixMatched(CDN_TYPES.Polyfill), "PolyfillPrefix", p => p.Substring("polyfill/".Length)), // polyfill.js from Fastly
(isPrefixMatched(CDN_TYPES.Microsoft), "AspNetCdnPrefix", p => p), // Libraries from Microsoft
(isPrefixMatched(CDN_TYPES.GitHub), "RawGitHubPrefix", p => p.Substring("raw/gh/".Length)),
(true, "BlobStoragePrefix", p => p) // fallback
};
foreach (var (isMatch, configKey, transform) in sources)
{
if (isMatch)
{
string prefix = Program.GetAppConfig(configKey);
if (await ServeBlob(context, transform(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();
}
}
}
}

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: 974 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 796 B

View File

@ -57,6 +57,7 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
@ -66,16 +67,31 @@
<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>
@ -84,9 +100,19 @@
</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>
@ -95,6 +121,9 @@
<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">
@ -127,5 +156,14 @@
<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

@ -1,3 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2"/></startup></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="CdnJsPrefix" value="https://cdnjs.cloudflare.com/"/>
<add key="JsDeliverPrefix" value="https://cdn.jsdelivr.net/"/>
<add key="UnpkgPrefix" value="https://unpkg.com/"/>
<add key="SkypackPrefix" value="https://www.skypack.dev/"/>
<add key="EsmShPrefix" value="https://esm.sh/"/>
<add key="EsmRunPrefix" value="https://esm.run/"/>
<add key="JqueryCdnPrefix" value="https://code.jquery.com/"/>
<add key="AspNetCdnPrefix" value="https://ajax.aspnetcdn.com/"/>
<add key="GoogleApisPrefix" value="https://ajax.googleapis.com/"/>
<add key="RawGitHubPrefix" value="https://raw.githubusercontent.com/"/>
</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>

View File

@ -42,5 +42,22 @@ namespace WelsonJS.Service
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

@ -6,11 +6,11 @@ using System.Runtime.InteropServices;
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
// 이러한 특성 값을 변경하세요.
[assembly: AssemblyTitle("WelsonJS.Service")]
[assembly: AssemblyDescription("Windows Service for WelsonJS framework")]
[assembly: AssemblyDescription("Windows Service for WelsonJS framework based applications")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Catswords")]
[assembly: AssemblyProduct("WelsonJS")]
[assembly: AssemblyCopyright("Catswords OSS, Opensource licensed under GPLv3")]
[assembly: AssemblyCopyright("Catswords OSS, GPLv3 or Ms-RL")]
[assembly: AssemblyTrademark("WelsonJS")]
[assembly: AssemblyCulture("")]
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
// 기본값으로 할 수 있습니다.
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.2.7.49")]
[assembly: AssemblyFileVersion("0.2.7.49")]
[assembly: AssemblyVersion("0.2.7.54")]
[assembly: AssemblyFileVersion("0.2.7.54")]

View File

@ -35,7 +35,6 @@ using WelsonJS.TinyINIController;
using System.Collections;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using WelsonJS.Service.Logging;
namespace WelsonJS.Service
{
@ -442,7 +441,7 @@ namespace WelsonJS.Service
if (index > 2)
{
var key = arg.Substring(2, index - 2);
var value = arg.Substring(index + 1);
var value = arg.Substring(index + 1).Trim('"');
arguments[key] = value;
}
else

View File

@ -9,10 +9,11 @@ namespace WelsonJS.Service
{
private ServiceMain parent;
private Dictionary<string, string> userVariables;
private readonly string envFilePath = Path.Combine(Path.GetTempPath(), "welsonjs_default.env");
private string envFilePath;
public UserVariables(ServiceBase parent)
{
envFilePath = Path.Combine(Program.GetAppDataPath(), "welsonjs_default.env");
this.parent = (ServiceMain)parent;
}

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

@ -11,29 +11,32 @@
* - https://github.com/gnh1201/welsonjs
* - https://catswords.social/@catswords_oss
* - https://teams.live.com/l/community/FEACHncAhq8ldnojAI
* - https://discord.gg/XKG5CjtXEj
*
* author:
* - Namhyeon Go <abuse@catswords.net>
* - @chandong83 (github.com) - Original author of CryptoHIGHT.cs
* - KISA(Korea Internet & Security Agency)
* - Korea Unversity
* 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://seed.kisa.or.kr/kisa/algorithm/EgovHightInfo.do
* - 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 static class HIGHT
public class HIGHT
{
private static readonly byte[] hightDelta = {
0x5A,0x6D,0x36,0x1B,0x0D,0x06,0x03,0x41,
@ -236,24 +239,6 @@ namespace WelsonJS.Cryptography
dataOut[6] = (byte)((xx[6] ^ scheduleKey[3]) & 0xFF);
}
void debugPrintHex(byte[] dat)
{
for (int i = 0; i < dat.Length; i++)
{
Console.Write(string.Format("0x{0:x2}, ", dat[i]));
if (((i + 1) % 16) == 0)
{
Console.WriteLine("");
}
}
Console.WriteLine("");
}
void debugPrintLine(string str)
{
Console.WriteLine(str);
}
void EncryptBlock(byte[] dataIn, byte[] dataOut)
{
byte[] xx = new byte[8];
@ -318,6 +303,7 @@ namespace WelsonJS.Cryptography
dataOut[4] = (byte)((xx[5] + scheduleKey[6]) & 0xFF);
dataOut[6] = (byte)((xx[7] ^ scheduleKey[7]) & 0xFF);
}
public byte[] Encrypt(byte[] dataIn)
{
int length;
@ -347,6 +333,7 @@ namespace WelsonJS.Cryptography
}
return dataOut;
}
public byte[] Decrypt(byte[] dataIn)
{
int length;
@ -376,7 +363,7 @@ namespace WelsonJS.Cryptography
return dataOut;
}
public void test()
public void Test()
{
byte[] dataIn = new byte[15];
byte[] dataOut = new byte[15];
@ -385,17 +372,17 @@ namespace WelsonJS.Cryptography
{
dataIn[i] = (byte)i;
}
debugPrintLine("schedule key data");
debugPrintHex(scheduleKey);
Console.WriteLine("schedule key data");
Console.WriteLine(string.Format("0x{0:x2}", scheduleKey));
dataOut = Encrypt(dataIn);
dataOut2 = Decrypt(dataOut);
debugPrintLine("origin data");
debugPrintHex(dataIn);
debugPrintLine("encryption data");
debugPrintHex(dataOut);
debugPrintLine("decryption data");
debugPrintHex(dataOut2);
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

@ -6,11 +6,11 @@ using System.Runtime.InteropServices;
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
// 이러한 특성 값을 변경하세요.
[assembly: AssemblyTitle("WelsonJS.Toolkit")]
[assembly: AssemblyDescription("Toolkit for WelsonJS framework")]
[assembly: AssemblyDescription("Toolkit for WelsonJS framework based applications")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Catswords")]
[assembly: AssemblyProduct("WelsonJS")]
[assembly: AssemblyCopyright("Catswords OSS, Opensource licensed under GPLv3")]
[assembly: AssemblyCopyright("Catswords OSS, GPLv3 or Ms-RL")]
[assembly: AssemblyTrademark("WelsonJS")]
[assembly: AssemblyCulture("")]
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
// 기본값으로 할 수 있습니다.
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.2.7.49")]
[assembly: AssemblyFileVersion("0.2.7.49")]
[assembly: AssemblyVersion("0.2.7.54")]
[assembly: AssemblyFileVersion("0.2.7.54")]

View File

@ -89,7 +89,12 @@
<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" />

32
app.js
View File

@ -4,8 +4,9 @@
//
// Author: Namhyeon Go <abuse@catswords.net>
// Repository: https://github.com/gnh1201/welsonjs
// License: GPLv3 or MS-RL (Opensource)
// Report abuse: abuse@catswords.net
// Latest news: [ActivityPub @catswords_oss@catswords.social](https://catswords.social/@catswords_oss)
// Latest news: ActivityPub @catswords_oss@catswords.social
// Join our team: https://teams.live.com/l/community/FEACHncAhq8ldnojAI
//
"use strict";
@ -83,6 +84,9 @@ var console = {
}
var message = messages.join(' ');
if (typeof type !== "undefined") {
message = type + ": " + message;
}
this._echoDefault(message);
this._messages.push(message);
@ -211,10 +215,12 @@ function require(pathname) {
if (cache[FN]) return cache[FN];
var T = null;
var pos = FN.indexOf('://');
var sep = '://', pos = FN.indexOf(sep);
if (pos > -1) {
var scheme = FN.substring(0, pos);
// load script from a remote server
if (["http", "https"].indexOf(FN.substring(0, pos)) > -1) {
if (["http", "https"].indexOf(scheme) > -1) {
require._addScriptProvider(function(url) {
try {
return require("lib/http").get(url);
@ -223,7 +229,25 @@ function require(pathname) {
}
});
}
// load script from LIE(Language Inference Engine) service
if (["ai"].indexOf(scheme) > -1) {
require._addScriptProvider(function(url) {
try {
var text = url.substring(pos + sep.length);
return require("lib/language-inference-engine")
.create()
.setProvider("openai")
.inference(text, 0)
.join(' ')
;
} catch (e) {
return null;
}
});
}
// if exists the custom script providers
if (require._scriptProviders.length > 0) {
var i = 0;
while (T == null && i < require._scriptProviders.length) {

View File

@ -1471,8 +1471,8 @@ matrix.determinant = function (m) {
while (numberOfAddedRows < numRow - 1) {
newArray.push(m[numberOfAddedRows + 1].slice(0, indexColumn).concat(m[numberOfAddedRows + 1].slice(indexColumn + 1)));
numberOfAddedRows++;
}
}
result += Math.pow(-1, indexColumn) * m[0][indexColumn] * matrix.determinant(newArray);
indexColumn++;
}

View File

@ -1,15 +0,0 @@
#-*- coding: utf-8 -*-
import sys
def main(args):
if len(args) < 2:
print("Insufficient arguments")
sys.exit()
encoded_domain = args[1].encode('idna').decode("utf-8")
print(encoded_domain)
if __name__ == "__main__":
main(sys.argv)

View File

@ -0,0 +1,86 @@
Windows Registry Editor Version 5.00
;.JS file type association fix - Windows XP
;Author : Ramesh Srinivasan
;Created : Aug 30, 2007
;Homepage: http://www.winhelponline.com
[HKEY_CLASSES_ROOT\.JS]
@="JSFile"
"CachedFilterIID"="{c1243ca0-bf96-11cd-b579-08002b30bfeb}"
[HKEY_CLASSES_ROOT\.JS\PersistentHandler]
@="{5e941d80-bf96-11cd-b579-08002b30bfeb}"
[HKEY_CLASSES_ROOT\JSFile]
@="JScript Script File"
"FriendlyTypeName"=hex(2):40,00,25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,\
00,6f,00,6f,00,74,00,25,00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,\
32,00,5c,00,77,00,73,00,68,00,65,00,78,00,74,00,2e,00,64,00,6c,00,6c,00,2c,\
00,2d,00,34,00,38,00,30,00,34,00,00,00
[HKEY_CLASSES_ROOT\JSFile\DefaultIcon]
@=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,\
00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,57,00,53,00,\
63,00,72,00,69,00,70,00,74,00,2e,00,65,00,78,00,65,00,2c,00,33,00,00,00
[HKEY_CLASSES_ROOT\JSFile\ScriptEngine]
@="JScript"
[HKEY_CLASSES_ROOT\JSFile\ScriptHostEncode]
@="{85131630-480C-11D2-B1F9-00C04F86C324}"
[HKEY_CLASSES_ROOT\JSFile\Shell]
[HKEY_CLASSES_ROOT\JSFile\Shell\Edit]
@="&Edit"
[HKEY_CLASSES_ROOT\JSFile\Shell\Edit\Command]
@="notepad.exe \"%1\""
[HKEY_CLASSES_ROOT\JSFile\Shell\Open]
@="&Open"
[HKEY_CLASSES_ROOT\JSFile\Shell\Open\Command]
@=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,\
00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,57,00,53,00,\
63,00,72,00,69,00,70,00,74,00,2e,00,65,00,78,00,65,00,20,00,22,00,25,00,31,\
00,22,00,20,00,25,00,2a,00,00,00
[HKEY_CLASSES_ROOT\JSFile\Shell\Open2]
@="Open &with Command Prompt"
[HKEY_CLASSES_ROOT\JSFile\Shell\Open2\Command]
@=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,\
00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,43,00,53,00,\
63,00,72,00,69,00,70,00,74,00,2e,00,65,00,78,00,65,00,20,00,22,00,25,00,31,\
00,22,00,20,00,25,00,2a,00,00,00
[HKEY_CLASSES_ROOT\JSFile\Shell\Print]
@="&Print"
[HKEY_CLASSES_ROOT\JSFile\Shell\Print\Command]
@=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,\
00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,4e,00,6f,00,\
74,00,65,00,70,00,61,00,64,00,2e,00,65,00,78,00,65,00,20,00,2f,00,70,00,20,\
00,25,00,31,00,00,00
[HKEY_CLASSES_ROOT\JSFile\ShellEx]
[HKEY_CLASSES_ROOT\JSFile\ShellEx\DropHandler]
@="{60254CA5-953B-11CF-8C96-00AA00B8708C}"
[HKEY_CLASSES_ROOT\JSFile\ShellEx\PropertySheetHandlers]
[HKEY_CLASSES_ROOT\JSFile\ShellEx\PropertySheetHandlers\WSHProps]
@="{60254CA5-953B-11CF-8C96-00AA00B8708C}"
[HKEY_CLASSES_ROOT\JScript]
@="JScript Language"
[HKEY_CLASSES_ROOT\JScript\CLSID]
@="{f414c260-6ac0-11cf-b6d1-00aa00bbbb58}"
[HKEY_CLASSES_ROOT\JScript\OLEScript]

View File

@ -48,7 +48,13 @@ Router.add('/test', function(render) {
};
var content = FILE.readFile(test_profile_filepath, FILE.CdoCharset.CdoUTF_8);
var data = JSON.parse(content);
var data;
try {
data = JSON.parse(content);
} catch (e) {
throw Error("JSON parse error: " + e.message);
}
render("app/test.html", {
"data": data
});

View File

@ -2,7 +2,7 @@
<div class="col width-fill">
<div class="col">
<div class="panel cell">
<div class="header">기능 테스트 목록</div>
<div class="header">List of feature tests</div>
{{for data.tests}}
<div class="body">
<div class="cell">
@ -11,9 +11,9 @@
<div class="col width-fill mobile-width-fill" style="position: relative">
<span class="float-right" style="position: absolute; top: 0; right: 0;">
{{if id == 'gui_check'}}
<button class="button" type="button" onclick="javascript:gui_check()">시험</button>
<button class="button" type="button" onclick="javascript:gui_check()">Test</button>
{{else}}
<button class="button" type="button" onclick="javascript:test_start('{{:id}}')">시험</button>
<button class="button" type="button" onclick="javascript:test_start('{{:id}}')">Test</button>
{{/if}}
</span>
<div class="col width-fill mobile-width-fill">

View File

@ -1,26 +1,50 @@
REM bootstrap.bat
REM WelsonJS 0.2.7
REM https://github.com/gnh1201/welsonjs
REM WelsonJS 0.2.7 bootstrapping script
REM Source code available: https://github.com/gnh1201/welsonjs
@echo off
pushd %~dp0
echo [*] Starting pre-configure script...
:: Define variables
set TOOLKIT_URL=https://catswords.blob.core.windows.net/welsonjs/welsonjs_toolkit_latest.cab
set TOOLKIT_PATH=%APPDATA%\welsonjs\welsonjs_toolkit_latest.cab
set TOOLKIT_EXTRACT_PATH=%APPDATA%\welsonjs
set REGASM_PATH=%WINDIR%\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe
set LOCAL_TOOLKIT_DLL=bin\x86\WelsonJS.Toolkit.dll
set DOWNLOADED_TOOLKIT_DLL=%APPDATA%\welsonjs\WelsonJS.Toolkit.dll
echo [*] Registering HTA file association...
:: Ensure directory exists
if not exist "%APPDATA%\welsonjs" mkdir "%APPDATA%\welsonjs"
echo [*] Initializing WelsonJS pre-configuration...
:: Register HTA file association
echo [*] Configuring HTA file association...
reg import app\assets\reg\Default_HTA.reg
echo [*] Unlocking the performance limit of MSHTML...
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
rem echo [*] Registering AutoItX component...
rem regsvr32 /s "%PROGRAMFILES(X86)%\AutoIt3\AutoItX\AutoItX3.dll"
rem regsvr32 /s "%PROGRAMFILES(X86)%\AutoIt3\AutoItX\AutoItX3_x64.dll"
:: Determine which toolkit to use
if exist "%LOCAL_TOOLKIT_DLL%" (
echo [*] Local toolkit found. Using "%LOCAL_TOOLKIT_DLL%" for registration.
set TOOLKIT_DLL=%LOCAL_TOOLKIT_DLL%
) else if exist "%DOWNLOADED_TOOLKIT_DLL%" (
echo [*] Downloaded toolkit found. Using "%DOWNLOADED_TOOLKIT_DLL%" for registration.
set TOOLKIT_DLL=%DOWNLOADED_TOOLKIT_DLL%
) else (
echo [*] Toolkit not found locally. Downloading from external source...
:: Download the latest WelsonJS.Toolkit component
bitsadmin /transfer toolkit_download /download /priority normal %TOOLKIT_URL% %TOOLKIT_PATH%
:: Extract the downloaded CAB file
echo [*] Extracting WelsonJS.Toolkit component...
expand %TOOLKIT_PATH% -F:* %TOOLKIT_EXTRACT_PATH%
:: Set the downloaded DLL as the target
set TOOLKIT_DLL=%DOWNLOADED_TOOLKIT_DLL%
)
:: Register the WelsonJS.Toolkit component
echo [*] Registering WelsonJS.Toolkit component...
%WINDIR%\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe /codebase bin\x86\WelsonJS.Toolkit.dll
REM %WINDIR%\Microsoft.NET\Framework64\v2.0.50727\RegAsm.exe /codebase bin\x64\WelsonJS.Toolkit.dll
echo [*] Done.
%REGASM_PATH% /codebase %TOOLKIT_DLL%
:: Final step
echo [*] Pre-configuration complete. Starting bootstrap script...
cscript app.js bootstrap

16
data/apikey.json Normal file
View File

@ -0,0 +1,16 @@
{
"chatgpt": "file:data/chatgpt_apikey.txt",
"anthropic": "file:data/anthropic_apikey.txt",
"groq": "file:data/groq_apikey.txt",
"grok": "file:data/grok_apikey.txt",
"gemini": "file:data/gemini_apikey.txt",
"mistral": "file:data/mistral_apikey.txt",
"deepseek": "file:data/deepseek_apikey.txt",
"moonshot": "file:data/moonshot_apikey.txt",
"clovastudio": "file:data/clovastudio_apikey.txt",
"catswords-ai": "file:data/catswords_ai_apikey.txt",
"scrapeops": "file:data/scrapeops_apikey.txt",
"searchapi": "file:data/searchapi_apikey.txt",
"aviationstack": "file:data/aviationstack_apikey.txt",
"abuseipdb": "file:data/abuseipdb_apikey.txt"
}

View File

@ -0,0 +1,80 @@
[
{
"type": "stateless",
"provider": "scrapeops",
"url": "https://proxy.scrapeops.io/v1/?api_key={api_key}&url={url}&render_js={render_js}&residential={residential}&country={country}&keep_headers={keep_headers}",
"documentation": "https://scrapeops.io?fpr=namhyeon75"
},
{
"type": "stateful",
"provider": "scrapeops",
"url": "http://scrapeops:{api_key}@residential-proxy.scrapeops.io:8181",
"documentation": "https://scrapeops.io?fpr=namhyeon75"
},
{
"type": "serp",
"provider": "searchapi",
"url": "https://www.searchapi.io/api/v1/search?api_key={api_key}&engine={engine}&q={q}",
"documentation": "https://www.searchapi.io/?via=namhyeon"
},
{
"type": "serp",
"provider": "librey",
"url": "https://serp.catswords.net/librex/api.php?q={q}&p=1&t=0",
"documentation": "https://github.com/Ahwxorg/LibreY"
},
{
"type": "serp",
"provider": "invidious",
"url": "https://invidious.jing.rocks/invidious/api/v1/search?q={q}",
"documentation": "https://docs.invidious.io/instances/"
},
{
"type": "stateless-jsonrpc2",
"provider": "github.com/gnh1201/caterpillar",
"url": "http://localhost:8080",
"documentation": "https://github.com/gnh1201/caterpillar"
},
{
"type": "stateful",
"provider": "github.com/gnh1201/caterpillar",
"url": "http://localhost:5555",
"documentation": "https://github.com/gnh1201/caterpillar"
},
{
"type": "stateful",
"provider": "cloudflare",
"url": "http://localhost:40000",
"documentation": "https://developers.cloudflare.com/warp-client/warp-modes/"
},
{
"type": "stateful",
"provider": "fiddler",
"url": "http://localhost:8888",
"documentation": "https://www.telerik.com/fiddler/fiddler-classic"
},
{
"type": "stateful",
"provider": "fiddler2",
"url": "http://localhost:8866",
"documentation": "https://www.telerik.com/fiddler/fiddler-everywhere"
},
{
"type": "stateful",
"provider": "mitmproxy",
"url": "http://localhost:8080",
"documetation": "https://mitmproxy.org/"
},
{
"type": "stateful",
"provider": "burpsuite",
"url": "http://localhost:8080",
"documetation": "https://portswigger.net/burp"
},
{
"type": "stateful",
"provider": "zaproxy",
"url": "http://localhost:8080",
"documetation": "https://www.zaproxy.org/"
}
]

View File

@ -0,0 +1,6 @@
[
{
"role": "system",
"content": "If external information is required, provide the response according to the given conditions:\n\n* The type field should specify the search type (e.g., weather, location, stock, news, keyword), and the query field should specify the search target.\n* For types that require location information, request location information first.\n* The format must be in JSON-RPC 2.0.\n* The method should always be fixed as `get_search`."
}
]

View File

@ -0,0 +1,6 @@
[
{
"role": "system",
"content": "외부 정보가 필요한 경우 주어진 조건에 맞는 응답을 보내줘.\n\n* type 필드에 검색 유형(예: weather, location, stock, news, keyword), query 필드에 검색 대상을 지정\n* 위치 정보가 필요한 유형은 위치 정보를 먼저 요청\n* JSON-RPC 2.0 형식이여야 함.\n* method는 get_search으로 고정되어야 함."
}
]

View File

@ -1,6 +1,6 @@
{
"description": "WelsonJS test profile (test-misc.json)",
"updated_on": "2024-11-15",
"updated_on": "2025-01-15",
"dependencies": {
"welsonjs": "0.2.7"
},
@ -93,18 +93,28 @@
},
{
"id": "proxy_custom_provider",
"description": "HTTP proxy with an web proxy provider",
"description": "HTTP request with an web proxy provider",
"tags": ["Network", "HTTP"]
},
{
"id": "proxy_serp",
"description": "HTTP proxy with a SERP provider",
"description": "HTTP request with a SERP provider",
"tags": ["Network", "HTTP"]
},
{
"id": "proxy_stateless_jsonrpc2",
"description": "HTTP request with a JSON-RPC 2.0 based stateless proxy",
"tags": ["Network", "HTTP"]
},
{
"id": "numbers_test",
"description": "number.js test",
"tags": ["Mathematics"]
},
{
"id": "backup_vmware_esxi",
"description": "Open Virtualization Format (OVF) Tool for Broadcom/VMware virtualization infrastructures",
"tags": ["Virtualization"]
}
]
}

View File

@ -39,358 +39,565 @@
"tests": [
{
"id": "es5_polyfills",
"description": "ES5 수준 이상의 폴리필(Polyfill) 성공 여부 (Windows 내장 엔진에서 ES5 수준 이상의 폴리필 수행)",
"tags": ["Javascript 엔진", "ECMAScript Polyfills"]
"description": "Indicates Whether Polyfill higher than ES5 level has successfully performed (Perform pollyfill higher than ES5 level in Windows built-in Engine)",
"tags": [
"Javascript engine",
"ECMAScript Polyfills"
]
},
{
"id": "registry_find_provider",
"description": "레지스트리 제공자 찾기",
"tags": ["Windows 시스템", "레지스트리(Registry) 제어"]
"description": "find registry provider",
"tags": [
"Windows Systems",
"Control Registry"
]
},
{
"id": "registry_write",
"description": "레지스트리 쓰기",
"tags": ["Windows 시스템", "레지스트리(Registry) 제어"]
"description": "writing Registry",
"tags": [
"Windows Systems",
"control Registry"
]
},
{
"id": "registry_read",
"description": "레지스트리 읽기",
"tags": ["Windows 시스템", "레지스트리(Registry) 제어"]
"description": "reading Registry",
"tags": [
"Windows Systems",
"control Registry"
]
},
{
"id": "wmi_create_object",
"description": "WMI 오브젝트 생성",
"tags": ["Windows 시스템", "WMI(Windows Management Instrumentation) 제어"]
"description": "create WMI object",
"tags": [
"Windows Systems",
"control WMI(Windows Management Instrumentation) "
]
},
{
"id": "wmi_execute_query",
"description": "WMI 쿼리 실행",
"tags": ["Windows 시스템", "WMI(Windows Management Instrumentation) 제어"]
"description": "executing WMI query",
"tags": [
"Windows Systems",
"control WMI(Windows Management Instrumentation) "
]
},
{
"id": "wmi_result_query",
"description": "WMI 쿼리 결과",
"tags": ["Windows 시스템", "WMI(Windows Management Instrumentation) 제어"]
"description": "the result of WMI query",
"tags": [
"Windows Systems",
"control WMI(Windows Management Instrumentation) "
]
},
{
"id": "shell_create_object",
"description": "쉘(Shell) 오브젝트 생성",
"tags": ["Windows 시스템", "Windows 쉘(Shell)"]
"description": "create Shell object",
"tags": [
"Windows Systems",
"Windows Shell"
]
},
{
"id": "shell_build_command_line",
"description": "명령 행 빌드 (입력: Array Object, 출력: Unescaped Command String)",
"tags": ["Windows 시스템", "Windows 쉘(Shell)"]
"description": "building command line (input: Array Object, output: Unescaped Command String)",
"tags": [
"Windows Systems",
"Windows Shell"
]
},
{
"id": "shell_set_charset",
"description": "문자셋(Charset) 설정",
"tags": ["Windows 시스템", "Windows 쉘(Shell)"]
"description": "set Charset",
"tags": [
"Windows Systems",
"Windows Shell"
]
},
{
"id": "shell_working_directory",
"description": "작업 디렉토리(Working Directory) 설정",
"tags": ["Windows 시스템", "Windows 쉘(Shell)"]
"description": "set Working Directory",
"tags": [
"Windows Systems",
"Windows Shell"
]
},
{
"id": "shell_create_process",
"description": "프로세스 생성",
"tags": ["Windows 시스템", "Windows 쉘(Shell)"]
"description": "creating process",
"tags": [
"Windows Systems",
"Windows Shell"
]
},
{
"id": "shell_execute",
"description": "쉘 명령어 실행 (결과(stdout, stderr)를 수신)",
"tags": ["Windows 시스템", "Windows 쉘(Shell)"]
"description": "execute shell command (receive results(stdout, stderr))",
"tags": [
"Windows Systems",
"Windows Shell"
]
},
{
"id": "shell_run",
"description": "쉘 명령어 실행 (결과와 무관하게 fork)",
"tags": ["Windows 시스템", "Windows 쉘(Shell)"]
"description": "run shell command (fork)regardless of result",
"tags": "run shell command (fork) regardless of result"
},
{
"id": "shell_run_as",
"description": "쉘 명령어 실행 (관리자 권한으로 실행)",
"tags": ["Windows 시스템", "Windows 쉘(Shell)"]
"description": "run shell command (run with administrator's authority)",
"tags": [
"Windows Systems",
"Windows Shell"
]
},
{
"id": "shell_find_my_documents",
"description": "내 문서(My Documents) 위치 가져오기",
"tags": ["Windows 시스템", "Windows 쉘(Shell)"]
"description": "bring (My Documents) location",
"tags": [
"Windows Systems",
"Windows Shell"
]
},
{
"id": "shell_release",
"description": "생성된 쉘 오브젝트 해제",
"tags": ["Windows 시스템", "Windows 쉘(Shell)"]
"description": "release created shell object",
"tags": [
"Windows Systems",
"Windows Shell"
]
},
{
"id": "powershell_set_command",
"description": "실행할 명령(커맨드라인) 지정",
"tags": ["Windows 시스템", "Windows 파워쉘(Powershell)"]
"description": "Set command line to execute",
"tags": [
"Windows Systems",
"Windows Powershell"
]
},
{
"id": "powershell_set_file",
"description": "실행할 파일(*.ps1) 지정",
"tags": ["Windows 시스템", "Windows 파워쉘(Powershell)"]
"description": "set files(*.ps1)to execute",
"tags": [
"Windows Systems",
"Windows Powershell"
]
},
{
"id": "powershell_set_uri",
"description": "URI를 이용하여 명령 지정",
"tags": ["Windows 시스템", "Windows 파워쉘(Powershell)"]
"description": "Use URI to set commands",
"tags": [
"Windows Systems",
"Windows Powershell"
]
},
{
"id": "powershell_execute",
"description": "명령 실행 (유저 모드)",
"tags": ["Windows 시스템", "Windows 파워쉘(Powershell)"]
"description": "Execute command (user mode)",
"tags": [
"Windows Systems",
"Windows Powershell"
]
},
{
"id": "powershell_run_as",
"description": "명령 실행 (관리자 모드)",
"tags": ["Windows 시스템", "Windows 파워쉘(Powershell)"]
"description": "Execute command (administrator mode)",
"tags": [
"Windows Systems",
"Windows Powershell"
]
},
{
"id": "system_resolve_env",
"description": "환경변수 해석기(Resolver)가 환경변수를 적절히 해석하는지 확인",
"tags": ["Windows 시스템", "시스템 정보"]
"description": "Verify if the environment variable resolver interprets environment variables correctly",
"tags": [
"Windows Systems",
"System Information"
]
},
{
"id": "system_check_as",
"description": "현재 프로세스 자신이 관리자 모드인지 체크",
"tags": ["Windows 시스템", "시스템 정보"]
"description": "Check if the current process is in administrator mode",
"tags": [
"Windows Systems",
"System Information"
]
},
{
"id": "system_get_os_version",
"description": "현재 OS 버전 불러오기",
"tags": ["Windows 시스템", "시스템 정보"]
"description": "Get current OS version",
"tags": [
"Windows Systems",
"System Information"
]
},
{
"id": "system_get_architecture",
"description": "현재 아키텍쳐 불러오기",
"tags": ["Windows 시스템", "시스템 정보"]
"description": "Get current system architecture",
"tags": [
"Windows Systems",
"System Information"
]
},
{
"id": "system_get_uuid",
"description": "현재 장치 고유번호(UUID) 불러오기",
"tags": ["Windows 시스템", "시스템 정보"]
"description": "bringing the UUID of current device",
"tags": [
"Windows Systems",
"System Information"
]
},
{
"id": "system_get_working_directory",
"description": "현재 작업 디렉토리 불러오기",
"tags": ["Windows 시스템", "시스템 정보"]
"description": "bringing current working directory",
"tags": [
"Windows Systems",
"System Information"
]
},
{
"id": "system_get_script_directory",
"description": "현재 스크립트 디렉토리 불러오기",
"tags": ["Windows 시스템", "시스템 정보"]
"description": "bringing current script directory",
"tags": [
"Windows Systems",
"System Information"
]
},
{
"id": "system_get_network_interfaces",
"description": "네트워크 인터페이스 정보 불러오기",
"tags": ["Windows 시스템", "시스템 정보"]
"description": "bringing network interface information",
"tags": [
"Windows Systems",
"System Information"
]
},
{
"id": "system_get_process_list",
"description": "활성 프로세스 목록 불러오기",
"tags": ["Windows 시스템", "시스템 정보"]
"description": "get activated ",
"tags": [
"Windows Systems",
"System Information"
]
},
{
"id": "system_get_process_list_by_name",
"description": "프로세스 이름으로 특정 활성 프로세스 찾기",
"tags": ["Windows 시스템", "시스템 정보"]
"description": "find certain active process by process name",
"tags": [
"Windows Systems",
"System Information"
]
},
{
"id": "system_register_uri",
"description": "URI를 등록하고 URI 요청 내용에 따른 명령 수행",
"tags": ["Windows 시스템", "URI(Uniform Resource Identifier) 등록"]
"description": "Register URI and carry out command as URI has requested",
"tags": [
"Windows Systems",
"Register URI(Uniform Resource Identifier)"
]
},
{
"id": "system_pipe_ipc",
"description": "두개 이상의 프로세스 간 통신",
"tags": ["Windows 시스템", "IPC(프로세스 간 통신)"]
"description": "Interprocess communication between more than 2 processes",
"tags": [
"Windows Systems",
"IPC(Inter Process Communication)"
]
},
{
"id": "vhid_find_window",
"description": "활성창(Window) 핸들 찾기",
"tags": ["휴먼 인터페이스", "가상 휴면 인터페이스"]
"description": "find active window handle",
"tags": [
"human interface",
"virtual human interface"
]
},
{
"id": "vhid_send_click",
"description": "가상 클릭(Click) 보내기",
"tags": ["휴먼 인터페이스", "가상 휴면 인터페이스"]
"description": "send virtual click",
"tags": [
"human interface",
"virtual human interface"
]
},
{
"id": "vhid_send_keys",
"description": "가상 문자키(a-zA-Z0-9) 보내기",
"tags": ["휴먼 인터페이스", "가상 휴면 인터페이스"]
"description": "Send virtual text key (a-zA-Z0-9)",
"tags": [
"human interface",
"virtual human interface"
]
},
{
"id": "vhid_send_key_enter",
"description": "가상 엔터키 보내기",
"tags": ["휴먼 인터페이스", "가상 휴면 인터페이스"]
"description": "send virtual enter key",
"tags": [
"human interface",
"virtual human interface"
]
},
{
"id": "vhid_send_key_functions",
"description": "가상 FN키 보내기",
"tags": ["휴먼 인터페이스", "가상 휴면 인터페이스"]
"description": "Send virtual FN key",
"tags": [
"human interface",
"virtual human interface"
]
},
{
"id": "vhid_alert",
"description": "Alert() API 호출 시 메시지 출력 여부",
"tags": ["휴먼 인터페이스", "가상 휴면 인터페이스"]
"description": "Alert whether message output will be provided when API is called",
"tags": [
"human interface",
"virtual human interface"
]
},
{
"id": "vhid_confirm",
"description": "Confirm() API 호출 시 메시지 출력 및 Yes/No 선택",
"tags": ["휴먼 인터페이스", "가상 휴면 인터페이스"]
"description": "Confirm() message output when API is called and choose between Yes/No",
"tags": [
"human interface",
"virtual human interface"
]
},
{
"id": "vhid_prompt",
"description": "Prompt() API 호출 시 서술형 응답 받을 수 있음",
"tags": ["휴먼 인터페이스", "가상 휴면 인터페이스"]
"description": "Prompt() When calling API, can receive descriptive response",
"tags": [
"human interface",
"virtual human interface"
]
},
{
"id": "network_http_get",
"description": "HTTP GET 전송",
"tags": ["네트워크", "HTTP 전송 및 처리"]
"description": "Send HTTP GET",
"tags": [
"network",
"Send HTTP and handle HTTP"
]
},
{
"id": "network_http_post",
"description": "HTTP POST 전송",
"tags": ["네트워크", "HTTP 전송 및 처리"]
"description": "Send HTTP POST",
"tags": [
"network",
"send HTTP and handle HTTP"
]
},
{
"id": "network_http_extended",
"description": "HTTP 확장 메소드(FETCH, PUT 등) 전송",
"tags": ["네트워크", "HTTP 전송 및 처리"]
"description": "send HTTP extension methods(FETCH, PUT, etc)",
"tags": [
"network",
"send HTTP and handle HTTP"
]
},
{
"id": "network_attach_debugger",
"description": "HTTP 디버거(Fiddler 등) 설정(Attach) 지원",
"tags": ["네트워크", "HTTP 전송 및 처리"]
"description": "support attaching HTTP debugger(Fiddler, etc)",
"tags": [
"network",
"send HTTP and handle HTTP"
]
},
{
"id": "network_detect_charset",
"description": "HTTP 응답 본문에서 문자셋(Charset) 탐지",
"tags": ["네트워크", "HTTP 전송 및 처리"]
"description": "detect Charset in HTTP response body",
"tags": [
"network",
"send HTTP and handle HTTP"
]
},
{
"id": "network_detect_http_ssl",
"description": "접속 대상 웹사이트의 보안통신(SSL) 사용 여부 탐지",
"tags": ["네트워크", "HTTP 전송 및 처리"]
"description": "detect whether SSL is running in the website to access ",
"tags": [
"network",
"send HTTP and handle HTTP"
]
},
{
"id": "network_send_icmp",
"description": "PING(ICMP) 전송",
"tags": ["네트워크", "PING(ICMP) 전송"]
"description": "send PING(ICMP)",
"tags": [
"network",
"send PING(ICMP)"
]
},
{
"id": "extramath_dtm",
"description": "2개 이상의 주어진 문장으로부터 DTM (문서-용어 행렬) 생성",
"tags": ["고급 문자열 처리", "자연어 처리"]
"description": "create DTM (Document-Term Matrix) from more than 2 sentences that are provided",
"tags": [
"advanced string manipulation",
"natural language processing"
]
},
{
"id": "extramath_cosine_similarity",
"description": "주어진 두 문장의 유사도를 코사인 유사도로 비교",
"tags": ["고급 문자열 처리", "자연어 처리"]
"description": "compare the similarity of 2 given sentences with cosine similarity",
"tags": [
"advanced string manipulation",
"natural language processing"
]
},
{
"id": "base64_encode",
"description": "BASE64 인코딩",
"tags": ["고급 문자열 처리", "BASE64"]
"description": "BASE64 encoding",
"tags": [
"advanced string manipulation",
"BASE64"
]
},
{
"id": "base64_decode",
"description": "BASE64 디코딩",
"tags": ["고급 문자열 처리", "BASE64"]
"description": "BASE64 decoding",
"tags": [
"advanced string manipulation",
"BASE64"
]
},
{
"id": "chromium_run",
"description": "웹 브라우저 실행",
"tags": ["웹 브라우저 제어", "웹 브라우저 제어 (크로미움 계열)"]
"description": "run web browser",
"tags": [
"control web browser",
"control web browser (Chromium-based)"
]
},
{
"id": "chromium_create_profile",
"description": "프로파일 생성",
"tags": ["웹 브라우저 제어", "웹 브라우저 제어 (크로미움 계열)"]
"description": "create profile",
"tags": [
"control web browser",
"control web browser (Chromium-based)"
]
},
{
"id": "chromium_run_incognito",
"description": "개인정보 보호 모드로 웹 브라우저 실행",
"tags": ["웹 브라우저 제어", "웹 브라우저 제어 (크로미움 계열)"]
"description": "run web browser in incognito mode",
"tags": [
"control web browser",
"control web browser (Chromium-based)"
]
},
{
"id": "chromium_navigate",
"description": "URL로 주소 이동",
"tags": ["웹 브라우저 제어", "웹 브라우저 제어 (크로미움 계열)"]
"description": "move to another address through URL",
"tags": [
"control web browser",
"control web browser (Chromium-based)"
]
},
{
"id": "chromium_get_active_pages",
"description": "활성 페이지 목록 불러오기",
"tags": ["웹 브라우저 제어", "웹 브라우저 제어 (크로미움 계열)"]
"description": "bringing active page list",
"tags": [
"control web browser",
"control web browser (Chromium-based)"
]
},
{
"id": "chromium_find_page_by_id",
"description": "고유 ID로 페이지 찾기",
"tags": ["웹 브라우저 제어", "웹 브라우저 제어 (크로미움 계열)"]
"description": "finding page by original ID",
"tags": [
"control web browser",
"control web browser (Chromium-based)"
]
},
{
"id": "chromium_find_pages_by_title",
"description": "페이지 제목으로 페이지 찾기",
"tags": ["웹 브라우저 제어", "웹 브라우저 제어 (크로미움 계열)"]
"description": "finding pages by title of the pages",
"tags": [
"control web browser",
"control web browser (Chromium-based)"
]
},
{
"id": "chromium_move_focused",
"description": "창 포커스 이동",
"tags": ["웹 브라우저 제어", "웹 브라우저 제어 (크로미움 계열)"]
"description": "move focus of the window",
"tags": [
"control web browser",
"control web browser (Chromium-based)"
]
},
{
"id": "chromium_adjust_window_size",
"description": "창 크기 제어",
"tags": ["웹 브라우저 제어", "웹 브라우저 제어 (크로미움 계열)"]
"description": "adjust size of the window",
"tags": [
"control web browser",
"control web browser (Chromium-based)"
]
},
{
"id": "chromium_get_element_position",
"description": "제공된 CSS Selector와 일치하는 단일 객체 포지션 찾기",
"tags": ["웹 브라우저 제어", "웹 브라우저 제어 (크로미움 계열)"]
"description": "finding single element position that matches with provided CSS Selector",
"tags": [
"control web browser",
"control web browser (Chromium-based)"
]
},
{
"id": "chromium_get_mapreduced_element_position",
"description": "CSS Selector와 일치하는 다중 객체 중 조건에 맞는 객체의 포지션 찾기",
"tags": ["웹 브라우저 제어", "웹 브라우저 제어 (크로미움 계열)"]
"description": "finding position of the element that meets requirement among multiple elements that match with CSS selector",
"tags": [
"control web browser",
"control web browser (Chromium-based)"
]
},
{
"id": "chromium_set_value_to_textbox",
"description": "대상 객체가 사용자 입력형(TextArea 또는 TextInput인 경우) 값 설정하기",
"tags": ["웹 브라우저 제어", "웹 브라우저 제어 (크로미움 계열)"]
"description": "setting the value in case the object of the action is input by users(TextArea or TextInput)",
"tags": [
"control web browser",
"control web browser (Chromium-based)"
]
},
{
"id": "chromium_send_click",
"description": "가상 클릭(Click) 보내기",
"tags": ["웹 브라우저 제어", "웹 브라우저 제어 (크로미움 계열)"]
"description": "send virtual click",
"tags": [
"control web browser",
"control web browser (Chromium-based)"
]
},
{
"id": "chromium_send_keys",
"description": "가상 키(Key) 보내기",
"tags": ["웹 브라우저 제어", "웹 브라우저 제어 (크로미움 계열)"]
"description": "send virtual key",
"tags": [
"control web browser",
"control web browser (Chromium-based browser)"
]
},
{
"id": "chromium_auto_scroll_until_end",
"description": "수직 스크롤이 있을 시 스크롤이 끝날 때까지 자동으로 화면 탐색하기",
"tags": ["웹 브라우저 제어", "웹 브라우저 제어 (크로미움 계열)"]
"description": "exploring the screen automatically until the scrolling finishes, in case of vertical scrolling",
"tags": [
"control web browser",
"control web browser (Chromium-based browser)"
]
},
{
"id": "grpc_run_server",
"description": "gRPC 서버 실행",
"tags": ["gRPC"]
"description": "run gRPC server",
"tags": [
"gRPC"
]
},
{
"id": "grpc_receive_command",
"description": "gRPC로 들어온 명령을 스크립트로 받음",
"tags": ["gRPC"]
"description": "receive command that is sent to grpc in script",
"tags": [
"gRPC"
]
},
{
"id": "gui_check",
"description": "WebView (GUI) 환경에서도 (1)Windows 시스템/Windows 쉘(Shell), (2)Windows 시스템/WMI 제어 기능이 동작 가능.",
"tags": ["WebView"]
"description": "Even in WebView (GUI) environment, (1)Windows Systems/Windows Shell, (2)(Windows Systems/WMI control functions work.",
"tags": [
"WebView"
]
}
]
}
}

3
examples/hanoi.ai.js Normal file
View File

@ -0,0 +1,3 @@
// hanoi.ai.js
var hanoi = require("ai://hanoi tower example");
hanoi.test();

View File

@ -24,10 +24,10 @@ function main(args) {
var lines = [];
var wbInstance = Chrome.startWithDebugging("https://virustotal.com", null, "virustotal", 9222);
// 대기
// Wait
sleep(5000);
// 브라우저 탭 찾기
// finding browser tap
pages = wbInstance.getPagesByTitle("VirusTotal");
if (pages.length > 0) {
page = pages[0];
@ -38,12 +38,12 @@ function main(args) {
var callback1 = function(row) {
var hash = row[1];
console.log("탐색을 시도합니다:", hash);
console.log("Attempt exploring:", hash);
wbInstance.navigate("https://www.virustotal.com/gui/file/" + hash);
sleep(RAND.getInt(4000, 5000));
// 자료를 찾았는지 여부
// Indicates whether data was found
var msgNotFound = wbInstance.getEvaluatedValue(
"__getDocument().querySelector('vt-ui-shell').shadowRoot.querySelector('#mainContent').querySelector('slot').assignedNodes()[2]" +
wbInstance.getShadowRootSelector([
@ -53,12 +53,12 @@ function main(args) {
".shadowRoot.querySelector('.title slot').assignedNodes()[0].innerText"
);
if (msgNotFound == "No matches found") {
console.log("찾을 수 없음 (No matches found): " + hash);
console.log("No matches found"): " + hash);
lines.push([hash, '', '0', '0', '0', ''].join(','));
return;
}
// 전체 진단 수 확인
// Check how many times it was examined to detect and diagnose viruses
var positives = wbInstance.getEvaluatedValue(
"__getDocument().querySelector('vt-ui-shell').shadowRoot.querySelector('#mainContent').querySelector('slot').assignedNodes()[2]" +
wbInstance.getShadowRootSelector([
@ -69,7 +69,7 @@ function main(args) {
".shadowRoot.querySelector('div > div > div.positives').innerText"
);
// 알려진 파일 명
// known filename
var filename = wbInstance.getEvaluatedValue(
"__getDocument().querySelector('vt-ui-shell').shadowRoot.querySelector('#mainContent').querySelector('slot').assignedNodes()[2]" +
wbInstance.getShadowRootSelector([
@ -79,7 +79,7 @@ function main(args) {
".shadowRoot.querySelector('div > div.card-body > div > div.hstack.gap-4 > div.vstack.gap-2.align-self-center.text-truncate > div.file-name.text-truncate > a').innerText"
);
// 최근 진단 날짜 확인
// Check the latest date of the examination to detect and diagnose a virus
var last = wbInstance.getEvaluatedValue(
"__getDocument().querySelector('vt-ui-shell').shadowRoot.querySelector('#mainContent').querySelector('slot').assignedNodes()[2]" +
wbInstance.getShadowRootSelector([
@ -89,7 +89,7 @@ function main(args) {
".shadowRoot.querySelector('div > div.card-body > div > div.hstack.gap-4 > div:nth-child(5) > vt-ui-time-ago').getAttribute('data-tooltip-text')"
);
// 국내 백신 진단 여부 확인
// Check whether a Korean vaccine programme has examined to detect and diagnose virus
var score_undetected = wbInstance.getEvaluatedValue(
'Object.values(' +
"__getDocument().querySelector('vt-ui-shell').shadowRoot.querySelector('#mainContent').querySelector('slot').assignedNodes()[2].querySelector('file-view').shadowRoot.querySelector('vt-ui-main-generic-report').querySelector('.tab-slot')" +
@ -100,13 +100,13 @@ function main(args) {
".querySelectorAll('.detection')).reduce(function(a, x) { if(/AhnLab|ALYac|ViRobot/.test(x.innerText) && x.innerText.indexOf('Undetected') > -1) a = a + 1; return a; }, 0)"
);
console.log("해시:", hash);
console.log("알려진 파일 이름:", filename);
console.log("전체 진단:", positives);
console.log("최근 날짜:", last);
console.log("국내 백신 미진단:", score_undetected + "건");
console.log("hash:", hash);
console.log("known filename:", filename);
console.log("examined the whole to detect and diagnose viruses :", positives);
console.log("date of the latest activity:", last);
console.log("Hasn ' t examined with a Korean vaccine programme to detect and diagnose viruses:", score_undetected + "건");
// 쓰기 줄 생성
// create lines for writing
lines.push([hash, filename, '1', positives, score_undetected, last].join(','));
};

View File

@ -26,10 +26,11 @@ REM sc config "%SERVICE_NAME%" start= auto
REM sc description "%SERVICE_NAME%" "Service installed via InstallUtil.exe"
REM Add parameters to the ImagePath registry key
REG ADD "HKLM\SYSTEM\CurrentControlSet\Services\%SERVICE_NAME%" /v ImagePath /t REG_EXPAND_SZ /d "\"%EXE_PATH%\" --working-directory=%CURRENT_DIR% --script-name=defaultService" /f
REG ADD "HKLM\SYSTEM\CurrentControlSet\Services\%SERVICE_NAME%" /v ImagePath /t REG_EXPAND_SZ /d "\"%EXE_PATH%\" --working-directory=\"%CURRENT_DIR%\" --script-name=defaultService" /f
echo Service "%SERVICE_NAME%" installed and configured successfully.
sc start "%SERVICE_NAME%"
echo Service "%SERVICE_NAME%" started.
pause
pause

View File

@ -1,18 +1,19 @@
// anthropic.js
// Namhyeon Go <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
// Anthropic API documentation: https://docs.anthropic.com/en/api/getting-started
//
// ***SECURITY NOTICE***
// Anthropic/Claude requires an internet connection, and data may be transmitted externally. Users must adhere to the terms of use and privacy policy.
// - Privacy Policy: https://www.anthropic.com/legal/privacy
//
var FILE = require("lib/file");
var HTTP = require("lib/http");
function loadApiKey() {
var s = FILE.readFile("data/anthropic-apikey.txt", FILE.CdoCharset.CdoUTF_8);
return s.trim();
}
var CRED = require("lib/credentials");
function chat(content) {
var answers = [];
var apikey = loadApiKey();
var apikey = CRED.get("apikey", "anthropic");
console.log("Anthropic (Claude) API KEY:", apikey);
var response = HTTP.create("MSXML")
@ -53,7 +54,7 @@ function chat(content) {
exports.chat = chat;
exports.VERSIONINFO = "Anthropic (Claude) interface (anthropic.js) version 0.1.1";
exports.VERSIONINFO = "Anthropic (Claude) interface (anthropic.js) version 0.1.4";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;

124
lib/archive.js Normal file
View File

@ -0,0 +1,124 @@
// archive.js
// File archiver library for WelsonJS framework
// Namhyeon Go (Catswords Research) <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
//
var SHELL = require("lib/shell");
var FILE = require("lib/file");
function ArchiveObject(engine) {
this.workingDirectory = "";
this.patterns = [];
this.readFormat = "";
this.writeFormat = "";
this.engine = null;
this.setReadFormat = function(readFormat) {
this.readFormat = readFormat;
return this;
};
this.setWriteFormat = function(writeFormat) {
this.writeFormat = writeFormat;
return this;
};
this.setEngine = function(engine) {
this.engine = engine;
if (this.engine == "cabinet") {
this.setReadFormat("cab");
this.setWriteFormat("cab");
}
// TODO: zip, 7z, rar
return this;
};
this.extractTo = function(filename, targetDirectory) {
var result;
if (this.engine == "cabinet") {
// compress cab to target directory
result = SHELL.exec([
"expand",
filename,
targetDirectory
]);
}
return result;
};
this.compressTo = function(filename) {
var result;
// https://superuser.com/questions/658021/whats-the-best-way-to-create-a-cab-file-of-multiple-files-quickly
if (this.engine == "cabinet") {
var directives = this.buildDirectives();
// create the directives file (temporary file)
var tmp = PipeIPC.connect("volatile");
tmp.write(directives);
var tmp_path = out.path;
tmp.close();
// compress to cab
SHELL.exec([
"makecab",
"/d",
"CabinetName1=" + filename,
"/d",
"DiskDirectoryTemplate=" + this.workingDirectory,
"/f",
tmp_path
]);
// destroy the temporary file
tmp.destroy();
}
return result;
};
this.buildDirectives = function() {
var directives = [];
if (this.engine == "cabinet") {
this.patterns.forEach(function(x) {
if (FILE.fileExists(x)) directives.push(x);
});
}
return directives.join("\r\n");
};
this.addFile = function(file) {
this.patterns.push(file);
return this;
};
// set default engines
this.create = function() {
if (typeof engine === "undefined") {
this.setEngine("cabinet");
};
return this;
};
this.create();
}
exports.create = function(engine) {
return new ArchiveObject(engine);
};
exports.VERSIONINFO = "File archiver library (archive.js) version 0.1-dev";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;

119
lib/aviation.js Normal file
View File

@ -0,0 +1,119 @@
// aviation.js
// Namhyeon Go <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
//
// ***SECURITY NOTICE***
// Aviation Data Integration requires an internet connection, and data may be transmitted externally. Users must adhere to the terms of use and privacy policy.
// - AviationStack website: https://aviationstack.com/?utm_source=FirstPromoter&utm_medium=Affiliate&fpr=namhyeon71
// - SearchApi website: https://www.searchapi.io/?via=namhyeon
//
var HTTP = require("lib/http");
var CRED = require("lib/credentials");
function getData(type, params, limit, offset) {
var params = params || {};
var limit = (function(n) {
return n > 0 ? n : 100;
}(parseInt(limit));
var offset = (function(n) {
return n > -1 ? n : 0;
}(parseInt(limit));
params["limit"] = limit;
params["offset"] = offset;
params["access_key"] = CRED.get("apikey", "aviationstack");
var response = HTTP.create()
.setParameters(params)
.open("GET", "https://api.aviationstack.com/v1/" + type)
.send();
return response.responseBody;
}
function getFlights(params, limit, offset) {
return getData("flights", params, limit, offset);
}
function getRoutes(params, limit, offset) {
return getData("routes", params, limit, offset);
}
function getAirports(params, limit, offset) {
return getData("airports", params, limit, offset);
}
function getAirlines(params, limit, offset) {
return getData("airlines", params, limit, offset);
}
function getAircraftTypes(params, limit, offset) {
return getData("aircraft_types", params, limit, offset);
}
function getCities(params, limit, offset) {
return getData("cities", params, limit, offset);
}
function getCountries(params, limit, offset) {
return getData("countries", params, limit, offset);
}
function getFlightSchedules(params, limit, offset) {
return getData("timetable", params, limit, offset);
}
function getFlightsFuture(params, limit, offset) {
return getData("flightsFuture", params, limit, offset);
}
function getRoundTrip(arrival_id, departure_id, outbound_date, return_date) {
var response = HTTP.create()
.setParameters({
"api_key": CRED.get("apikey", "searchapi"),
"arrival_id": arrival_id,
"departure_id": departure_id,
"engine": "google_flights",
"flight_type": "round_trip",
"outbound_date": outbound_date,
"return_date": return_date
})
.open("GET", "https://www.searchapi.io/api/v1/search")
.send();
return response.responseBody;
}
function getOneWay(arrival_id, departure_id, outbound_date) {
var response = HTTP.create()
.setParameters({
"api_key": CRED.get("apikey", "searchapi"),
"arrival_id": arrival_id,
"departure_id": departure_id,
"engine": "google_flights",
"flight_type": "one_way",
"outbound_date": outbound_date
})
.open("GET", "https://www.searchapi.io/api/v1/search")
.send();
return response.responseBody;
}
exports.getData = getData;
exports.getFlights = getFlights;
exports.getRoutes = getRoutes;
exports.getAirports = getAirports;
exports.getAirlines = getAirlines;
exports.getAircraftTypes = getAircraftTypes;
exports.getCities = getCities;
exports.getCountries = getCountries;
exports.getFlightSchedules = getFlightSchedules;
exports.getFlightsFuture = getFlightsFuture;
exports.getRoundTrip = getRoundTrip;
exports.getOneWay = getOneWay;
exports.VERSIONINFO = "Aviation Data Integration (aviation.js) version 0.1.3";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;

View File

@ -108,6 +108,36 @@ if (!window.addEventListener) {
})(window, document, global.Element.prototype, []);
}
// https://stackoverflow.com/questions/45552695/why-element-matches-polyfill-doesnt-work
// https://github.com/zloirock/core-js/issues/780
// https://github.com/joncasey/modern-hta/blob/master/src/element-closest.js
if (Element && Element.prototype) {
if (!Element.prototype.matches) {
Element.prototype.matches = Element.prototype.msMatchesSelector;
}
if (!Element.prototype.closest) {
Element.prototype.closest = function(selector) {
for (var p = this; p != null; p = p.parentElement) {
if (p.matches(selector)) return p;
}
};
}
}
// https://github.com/summernote/summernote/pull/4625
if (CanvasPixelArray && CanvasPixelArray.prototype) {
if (!CanvasPixelArray.prototype.join) {
CanvasPixelArray.prototype.join = function() {
var pxInfo = this, s = '';
for (var i = 0; i < pxInfo.length; i++) {
s += pxInfo[i].toString();
}
return s;
};
}
}
// getIEVersion()
function getIEVersion() {
var undef,
@ -254,7 +284,7 @@ exports.start = start;
exports.reload = reload;
exports.close = close;
exports.VERSIONINFO = "Browser Compatibility Library (browser.js) version 0.1.6";
exports.VERSIONINFO = "Browser Compatibility Layer (browser.js) version 0.1.7";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;

View File

@ -1,16 +1,20 @@
// chatgpt.js
// Namhyeon Go <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
//
// ***SECURITY NOTICE***
// ChatGPT requires an internet connection, and data may be transmitted externally. Users must adhere to the terms of use and privacy policy.
// - Privacy Policy: https://openai.com/policies/row-privacy-policy/
//
var FILE = require("lib/file");
var HTTP = require("lib/http");
function loadApiKey() {
var s = FILE.readFile("data/chatgpt-apikey.txt", FILE.CdoCharset.CdoUTF_8);
return s.trim();
}
var CRED = require("lib/credentials");
function chat(content) {
var s = '';
var apikey = loadApiKey();
console.log("ChatGPT API KEY:", apikey);
var answers = [];
var apikey = CRED.get("apikey", "chatgpt");
console.log("OpenAI (ChatGPT) API KEY:", apikey);
var response = HTTP.create("MSXML")
.setVariables({
@ -21,12 +25,15 @@ function chat(content) {
"Authorization": "Bearer {OPENAI_API_KEY}"
})
.setRequestBody({
"model": "gpt-3.5-turbo",
"model": "gpt-4o",
"messages": [
{
"role": "user",
"content": content
}
{
"role": "developer",
"content": "Write all future code examples in JavaScript ES3 using the exports variable. Include a test method with the fixed name test. Respond exclusively in code without blocks."
}, {
"role": "user",
"content": content
}
]
})
.open("post", "https://api.openai.com/v1/chat/completions")
@ -34,8 +41,10 @@ function chat(content) {
.responseBody
;
if (response.choices.length > 0) {
s += response.choices[0].message.content;
if ("choices" in response && response.choices.length > 0) {
response.choices.forEach(function(x) {
answers.push(x.message.content);
});
}
return s;
@ -43,7 +52,7 @@ function chat(content) {
exports.chat = chat;
exports.VERSIONINFO = "ChatGPT interface (chatgpt.js) version 0.1";
exports.VERSIONINFO = "OpenAI (ChatGPT) interface version 0.1.2";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;

32
lib/coupang.js Normal file
View File

@ -0,0 +1,32 @@
// coupang.js
// Namhyeon Go <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
//
// ***SECURITY NOTICE***
// Due to potential security issues, the Public API URL is not provided. If you need to request access, please refer to the project's contact information.
// You can download the server-side script that implements this functionality from the link below:
// https://github.com/gnh1201/caterpillar
//
var JsonRpc2 = require("lib/jsonrpc2");
function search(s) {
var rpc = JsonRpc2.create(JsonRpc2.DEFAULT_JSONRPC2_URL);
var result = rpc.invoke("relay_invoke_method", {
"callback": "load_script",
"requires": [
"https://scriptas.catswords.net/coupang.class.php"
],
"args": [
"$search = new CoupangProductSearch(); return $search->searchProducts('" + s + "')"
]
}, "");
return result.data;
}
exports.search = search;
exports.VERSIONINFO = "Coupang Product Search Client (coupang.js) version 0.1.1";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;

69
lib/credentials.js Normal file
View File

@ -0,0 +1,69 @@
// credentials.js
// Namhyeon Go <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
//
var FILE = require("lib/file");
var CREDENTIALS_DATA = [];
function getTextFromFile(filename) {
if (FILE.fileExists(filename)) {
return FILE.readFile(filename, FILE.CdoCharset.CdoUTF_8);
}
return "";
}
function readFromFile(type, filename) {
var data = JSON.parse(getTextFromFile(filename));
for (var provider in data) {
var prelude = "file:";
var value = (function(s) {
if (s.indexOf(prelude) == 0) {
var filename = s.substring(prelude.length);
return getTextFromFile(filename);
} else {
return s;
}
})(data[provider]);
push(type, provider, value);
}
}
function push(type, provider, value) {
CREDENTIALS_DATA.push({
"type": type,
"provider": provider,
"value": value
});
}
function get(type, provider, index) {
var index = index || 0;
var matches = CREDENTIALS_DATA.reduce(function(a, x) {
if (x.type == type && x.provider == provider) {
a.push(x.value);
}
return a;
}, []);
if (matches.length - 1 < index) {
return null;
}
return matches[index];
}
readFromFile("apikey", "data/apikey.json");
exports.readFromFile = readFromFile;
exports.push = push;
exports.get = get;
exports.VERSIONINFO = "Credential store (credentials.js) version 0.1";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;

53
lib/grok.js Normal file
View File

@ -0,0 +1,53 @@
// grok.js
// Namhyeon Go <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
//
// ***SECURITY NOTICE***
// Grok (x.ai) requires an internet connection, and data may be transmitted externally. Users must adhere to the terms of use and privacy policy.
// - Privacy Policy: https://x.ai/legal/privacy-policy
//
var FILE = require("lib/file");
var HTTP = require("lib/http");
var CRED = require("lib/credentials");
function chat(content) {
var answers = [];
var apikey = CRED.get("apikey", "grok");
console.log("Grok (x.ai) API KEY:", apikey);
var response = HTTP.create("MSXML")
.setVariables({
"GROK_API_KEY": apikey
})
.setHeaders({
"Content-Type": "application/json",
"Authorization": "Bearer {GROK_API_KEY}"
})
.setRequestBody({
"messages": [{
"role": "user",
"content": content
}],
"model": "grok-2-latest"
})
.open("post", "https://api.x.ai/v1/chat/completions")
.send()
.responseBody
;
if ("choices" in response && response.choices.length > 0) {
response.choices.forEach(function(x) {
answers.push(x.message.content);
});
}
return answers.join(' ');
}
exports.chat = chat;
exports.VERSIONINFO = "Grok (x.ai) interface version 0.1";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;

View File

@ -1,18 +1,19 @@
// groq.js
// Namhyeon Go <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
// Groq API documentation: https://console.groq.com/docs/api-reference
//
// ***SECURITY NOTICE***
// Groq requires an internet connection, and data may be transmitted externally. Users must adhere to the terms of use and privacy policy.
// - Privacy Policy: https://groq.com/privacy-policy/
//
var FILE = require("lib/file");
var HTTP = require("lib/http");
function loadApiKey() {
var s = FILE.readFile("data/groq-apikey.txt", FILE.CdoCharset.CdoUTF_8);
return s.trim();
}
var CRED = require("lib/credentials");
function chat(content) {
var answers = [];
var apikey = loadApiKey();
var apikey = CRED.get("apikey", "groq");
console.log("Groq (GroqCloud) API KEY:", apikey);
var response = HTTP.create("MSXML")
@ -40,7 +41,7 @@ function chat(content) {
exports.chat = chat;
exports.VERSIONINFO = "Groq (GroqCloud) interface (groq.js) version 0.1";
exports.VERSIONINFO = "Groq (GroqCloud) interface (groq.js) version 0.1.1";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;

View File

@ -1,6 +1,6 @@
// http.js
// HTTP REST Client for WelsonJS framework
// Namhyeon Go (Catswords Research) <abuse@catswords.net>
// HTTP REST API client for WelsonJS framework
// Namhyeon Go (Catswords Research) <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
var SYS = require("lib/system");
var FILE = require("lib/file");
@ -8,92 +8,20 @@ var SHELL = require("lib/shell");
var RAND = require("lib/rand");
var BASE64 = require("lib/base64");
var PipeIPC = require("lib/pipe-ipc");
var JsonRpc2 = require("lib/jsonrpc2");
var SERP = require("lib/serp");
var OS_NAME = SYS.getOS();
var OS_ARCH = SYS.getArch();
var DEVICE_UUID = SYS.getUUID();
var PROCESS_VERSION = SYS.getProcessVersion();
var DEFAULT_USER_AGENT = "WelsonJS/0.2.7 (" + OS_NAME + "; " + OS_ARCH + "; " + PROCESS_VERSION + "; " + DEVICE_UUID + "; abuse@catswords.net)";
var DEFAULT_USER_AGENT = "WelsonJS/0.2.7 (" + OS_NAME + "; " + PROCESS_VERSION + "; " + DEVICE_UUID + ")";
// If you have any suggestions for partnerships, please contact us at: abuse@catswords.net
var AVAILABLE_PROXIES = [
{
"type": "stateless",
"provider": "scrapeops",
"url": "https://proxy.scrapeops.io/v1/?api_key={api_key}&url={url}&render_js={render_js}&residential={residential}&country={country}&keep_headers={keep_headers}",
"documentation": "https://scrapeops.io?fpr=namhyeon75"
},
{
"type": "stateful",
"provider": "scrapeops",
"url": "http://scrapeops:{api_key}@residential-proxy.scrapeops.io:8181",
"documentation": "https://scrapeops.io?fpr=namhyeon75"
},
{
"type": "serp",
"provider": "searchapi",
"url": "https://www.searchapi.io/api/v1/search?api_key={api_key}&engine={engine}&q={q}",
"documentation": "https://www.searchapi.io/?via=namhyeon"
},
{
"type": "serp",
"provider": "librey",
"url": "https://serp.catswords.net/api.php?q={q}&p=1&t=0",
"documentation": "https://github.com/Ahwxorg/LibreY"
},
{
"type": "serp",
"provider": "invidious",
"url": "https://invidious.example.org/api/v1/search?q={q}",
"documentation": "https://docs.invidious.io/"
},
{
"type": "stateless-jsonrpc2",
"provider": "gnh1201/caterpillar",
"url": "http://localhost:5555",
"documentation": "https://github.com/gnh1201/caterpillar"
},
{
"type": "stateful",
"provider": "gnh1201/caterpillar",
"url": "http://localhost:5555",
"documentation": "https://github.com/gnh1201/caterpillar"
},
{
"type": "stateful",
"provider": "cloudflare",
"url": "http://localhost:40000",
"documentation": "https://developers.cloudflare.com/warp-client/warp-modes/"
},
{
"type": "stateful",
"provider": "fiddler",
"url": "http://localhost:8888",
"documentation": "https://www.telerik.com/fiddler/fiddler-classic"
},
{
"type": "stateful",
"provider": "fiddler2",
"url": "http://localhost:8866",
"documentation": "https://www.telerik.com/fiddler/fiddler-everywhere"
},
{
"type": "stateful",
"provider": "mitmproxy",
"url": "http://localhost:8080",
"documetation": "https://mitmproxy.org/"
},
{
"type": "stateful",
"provider": "burpsuite",
"url": "http://localhost:8080",
"documetation": "https://portswigger.net/burp"
},
{
"type": "stateful",
"provider": "zaproxy",
"url": "http://localhost:8080",
"documetation": "https://www.zaproxy.org/"
"type": "file",
"provider": "",
"url": "data/available_proxies.json",
"documentation": ""
}
];
@ -101,14 +29,14 @@ var HTTPObject = function(engine) {
this._interface = null;
this.contentType = "application/x-www-form-urlencoded";
this.requestBody = "";
this.requestBody = null;
this.responseBody = null;
this.method = "GET";
this.headers = {};
this.parameters = {};
this.dataType = null;
this.userAgent = DEFAULT_USER_AGENT;
this.isAsynchronous = false;
this.isAsync = false;
this.proxy = {
"enabled": false,
"type": "stateful",
@ -116,8 +44,11 @@ var HTTPObject = function(engine) {
"protocol": "http",
"host": "127.0.0.1",
"port": 80,
"credential": null, // { username: "user", password: "pass" }
"url": null // stateless only
"credential": null, // e.g. { username: "user", password: "pass" }
"method": null, // for stateless only. e.g. GET, POST
"url": null, // for stateless only. e.g. http://localhost:8080
"userAgent": "php-httpproxy/0.1.5 (Client; WelsonJS; abuse@catswords.net)", // for stateless only
"rpcMethod": "relay_fetch_url" // for stateless proxy
};
this.engine = (typeof(engine) !== "undefined" ? engine : "MSXML");
@ -155,6 +86,7 @@ var HTTPObject = function(engine) {
this.isLoggingCookie = false;
this.debuggingText = '';
this.curlVersion = "8.12.1_4";
this.curlOptions = [];
this.charset = FILE.CdoCharset.CdoUTF_8;
@ -187,11 +119,11 @@ var HTTPObject = function(engine) {
// the location of cURL binary
var arch = SYS.getArch();
if (arch.toLowerCase().indexOf("arm") > -1) {
this.setBinPath("bin\\x64\\curl-8.10.1_1-win64a-mingw\\bin\\curl.exe");
this.setBinPath("bin\\arm64\\curl-" + this.curlVersion + "-win64a-mingw\\bin\\curl.exe");
} else if (arch.indexOf("64") > -1) {
this.setBinPath("bin\\x64\\curl-8.10.1_1-win64-mingw\\bin\\curl.exe");
this.setBinPath("bin\\x64\\curl-" + this.curlVersion + "-win64-mingw\\bin\\curl.exe");
} else {
this.setBinPath("bin\\x86\\curl-8.10.1_1-win32-mingw\\bin\\curl.exe");
this.setBinPath("bin\\x86\\curl-" + this.curlVersion + "-win32-mingw\\bin\\curl.exe");
}
// do not clear after calling the `exec`
@ -211,6 +143,11 @@ var HTTPObject = function(engine) {
console.info(this.engine, "is use", binPath);
this._interface.setPrefix(binPath);
};
this.setCurlVersion = function(curlVersion) {
this.curlVersion = curlVersion;
this.setEngine("CURL");
};
this.jqEnabled = function() {
return (typeof(window) !== "undefined" && typeof(window.jQuery) !== "undefined");
@ -218,18 +155,18 @@ var HTTPObject = function(engine) {
this.jqAjax = function(url, callback, onError) {
var options = {
type: this.method,
type: this.getMethod(),
headers: this.headers,
url: this.serializeParameters(url),
//data: this.requestBody,
data: null,
contentType: this.contentType,
success: callback,
async: this.isAsynchronous,
error: onError // (request, status, error)
async: this.isAsync,
error: onError // f(request, status, error)
};
if (["POST", "PUT", "PATCH"].indexOf(this.method) > -1) {
options['data'] = this.requestBody;
options['data'] = this.serialize();
}
this.setResponseBody(window.jQuery.ajax(options).responseText);
@ -244,11 +181,11 @@ var HTTPObject = function(engine) {
if (this.dataType === "json") {
return true;
} else if (this.engine == "MSXML") {
var headers = this.getHeaders();
var headers = this.getResponseHeaders();
for (var key in headers) {
var _k = key.toLowerCase();
var _v = headers[key].toLowerCase();
if (_k === "content-type" && _v === "application/json") {
var header_key = key.toLowerCase();
var header_value = headers[key].toLowerCase();
if (header_key === "content-type" && header_value === "application/json") {
this.dataType = "json";
return true;
}
@ -283,7 +220,7 @@ var HTTPObject = function(engine) {
this.proxy.credential = availableProxy['credential'] || this.proxy.credential;
this.proxy.url = availableProxy['url'] || this.proxy.url;
console.info("Please check documentation:", availableProxy.documentation);
console.info("See the documentation:", availableProxy.documentation);
}
}
@ -295,6 +232,11 @@ var HTTPObject = function(engine) {
this.proxy[k] = proxy[k];
}
// When JSON-RPC 2.0 based stateless proxy
if (this.proxy.type == "stateless-jsonrpc2") {
this.proxy.method = "POST";
}
// check proxy configuration
console.info("Proxy Configuration:", JSON.stringify(this.proxy));
@ -302,9 +244,13 @@ var HTTPObject = function(engine) {
};
this.setMethod = function(method) {
this.method = method;
this.method = method.toUpperCase();
return this;
};
this.getMethod = function() {
return (this.proxy.method != null ? this.proxy.method : this.method);
};
this.setDataType = function(type) {
this.dataType = type;
@ -357,25 +303,24 @@ var HTTPObject = function(engine) {
}
}
} catch (e) {
console.error("HTTPObject.setHeaders() -> ", e.message);
console.error("Exception on HTTPObject.setHeaders():", e.message);
}
return this;
};
this.getHeader = function(key) {
this.getResponseHeader = function(key) {
try {
return this._interface.getResponseHeader(key);
} catch (e) {
console.error("HTTPObject.getHeader() -> ", e.message);
console.error("Exception on HTTPObject.getResponseHeader():", e.message);
}
};
this.getHeaders = function() {
this.getResponseHeaders = function(callback) {
try {
var raw = this._interface.getAllResponseHeaders();
return raw.split(/[\r\n]+/).filter(function(s) {
var text = this._interface.getAllResponseHeaders();
var headers = text.split(/[\r\n]+/).filter(function(s) {
return s.trim().length > 0;
}).map(function(s) {
return s.trim().split(": ");
@ -383,11 +328,33 @@ var HTTPObject = function(engine) {
acc[c[0].trim()] = c[1].trim();
return acc;
}, {});
if (typeof callback !== "function") {
return headers;
}
return callback(headers);
} catch (e) {
console.error("HTTPObject.getHeaders() -> ", e.message);
console.error("Exception on HTTPObject.getResponseHeaders():", e.message);
}
};
this.getRequestHeader = function(key) {
return this.headers[key];
}
this.getRequestHeaders = function(callback) {
try {
if (typeof callback !== "function") {
return this.headers;
}
return callback(this.headers);
} catch (e) {
console.error("Exception on HTTPObject.getRequestHeaders():", e.message);
}
};
this.setParameter = function(key, value) {
this.parameters[key] = value;
return this;
@ -405,7 +372,7 @@ var HTTPObject = function(engine) {
this.setParameter(key, value);
}
} catch (e) {
console.error("HTTPObject.setParameters() -> ", e.message);
console.error("Exception on HTTPObject.setParameters():", e.message);
}
return this;
};
@ -431,7 +398,7 @@ var HTTPObject = function(engine) {
};
this.setIsAsynchronous = function(flag) {
this.isAsynchronous = flag;
this.isAsync = flag;
return this;
}
@ -439,22 +406,46 @@ var HTTPObject = function(engine) {
this.userAgent = agent;
return this;
};
this.serialize = function() {
if (this.isJSONRequest() && typeof(this.requestBody) === "object") {
return JSON.stringify(this.requestBody);
} else if (typeof(this.requestBody) === "object") {
return this.serializeURL(this.evaluate(this.requestBody));
this.getUserAgent = function() {
return (this.proxy.userAgent != null ? this.proxy.userAgent : this.userAgent);
};
this.serialize = function(url) {
var data = "";
if (this.isJSONRequest() && typeof this.requestBody === "object") {
data = JSON.stringify(this.requestBody);
} else if (typeof this.requestBody === "object") {
data = this.serializeURL(this.requestBody);
} else {
return this.evaluate(this.requestBody);
data = this.evaluate(this.requestBody);
}
if (this.proxy.type == "stateless-jsonrpc2") {
data = JSON.stringify(
JsonRpc2.wrap(this.proxy.rpcMethod, {
"method": this.method,
"url": url,
"headers": this.getRequestHeaders(function(x) {
return Object.keys(x).reduce(function(a, k) {
a.push(k + ": " + x[k]);
return a;
}, []);
}),
"data": data
}, "")
);
}
return data;
};
this.serializeURL = function(parameters) {
this.serializeURL = function(params) {
var s = [];
for (var k in parameters) {
if (parameters.hasOwnProperty(k)) {
s.push(encodeURIComponent(k) + "=" + encodeURIComponent(this.evaluate(parameters[k])));
for (var k in params) {
if (params.hasOwnProperty(k)) {
s.push(encodeURIComponent(k) + "=" + encodeURIComponent(this.evaluate(params[k])));
}
}
return s.join("&");
@ -468,21 +459,21 @@ var HTTPObject = function(engine) {
// Bind parameters
if (Object.keys(this.parameters).length > 0) {
// Type 2
var parameters = {};
var params = {};
for (var k in this.parameters) {
if (url.indexOf(':' + k) > -1) {
url = url.replace(':' + k, this.evaluate(this.parameters[k]));
} else {
parameters[k] = this.evaluate(this.parameters[k]);
params[k] = this.evaluate(this.parameters[k]);
}
}
// Type 1
if (Object.keys(parameters).length > 0) {
if (Object.keys(params).length > 0) {
if (url.indexOf('?') > -1) {
url += '&' + this.serializeURL(parameters);
url += '&' + this.serializeURL(params);
} else {
url += '?' + this.serializeURL(parameters);
url += '?' + this.serializeURL(params);
}
}
}
@ -492,11 +483,11 @@ var HTTPObject = function(engine) {
return url;
};
this.getProxiedURL = function(url) {
this.getProxiedUrl = function(url) {
if (!this.proxy.enabled) return url;
if (this.proxy.type == "serp") {
var serp = this.parseSerpUrl(url);
var serp = SERP.parseUrl(url);
this.setVariable("engine", serp.engine);
this.setVariable("q", encodeURIComponent(serp.keyword));
}
@ -509,59 +500,30 @@ var HTTPObject = function(engine) {
return url;
};
this.parseSerpUrl = function(url) {
var getEngine = function(url) {
var match = url.match(/(?:https?:\/\/)?(?:www\.)?(google|youtube|bing|baidu|amazon|naver|daum)\.\w+/), result;
if (match) {
result = match[1];
if (result == "naver" || result == "daum") {
result = "google";
}
} else {
result = "google";
}
return result;
};
var getKeyword = function(url) {
var regex = /[?&](q|wd|query|search_query|k)=([^&]*)/g;
var match, keywords = [];
while ((match = regex.exec(url)) !== null) {
keywords.push(match[2]);
}
return keywords.join(' ');
};
return {
"engine": getEngine(url),
"keyword": getKeyword(url)
}
};
this.open = function(method, url) {
var url = this.serializeParameters(url);
this.setMethod(method.toUpperCase()); // set method
this.setMethod(method); // set method
this.pushState(null, null, url); // push state
this.setHeader("User-Agent", this.evaluate(this.userAgent)); // user agent
this.setHeader("User-Agent", this.evaluate(this.getUserAgent())); // user agent
try {
if (this.engine == "MSXML") {
// Get the proxied URL
url = this.getProxiedURL(url);
url = this.getProxiedUrl(url);
// Open the URL
switch (this.method) {
switch (this.getMethod()) {
case "POST":
this._interface.open(method, url, this.isAsynchronous);
this._interface.open("POST", url, this.isAsync);
break;
case "GET":
this._interface.open(method, url, this.isAsynchronous);
this._interface.open("GET", url, this.isAsync);
break;
default:
console.warn("Switching the engine to cURL. Not supported method in MSXML: " + method);
console.warn(this.method, "method not supported. Retrying with cURL...");
this.setEngine("CURL");
console.log("Use the engine:", this.engine);
}
@ -569,7 +531,7 @@ var HTTPObject = function(engine) {
console.log("Use the engine:", this.engine);
}
} catch (e) {
console.error("HTTPObject.open() ->", e.message);
console.error("Exception on HTTPObject.open():", e.message);
}
return this;
@ -579,6 +541,17 @@ var HTTPObject = function(engine) {
var responseText = null;
var debuggingText = null;
// check exists the opened states
if (this.states.length == 0) {
console.error("No available states");
return;
}
// get opened URL from last states
var state = this.states[this.states.length - 1];
var target_url = state.url;
var url = this.getProxiedUrl(target_url);
// [lib/http] cURL error with non-escaped ampersand on Command Prompt #103
var replaceAndExcludeCaretAnd = function(inputString) {
var result = "";
@ -613,13 +586,13 @@ var HTTPObject = function(engine) {
this._interface.setRequestHeader(key, this.evaluate(this.headers[key]));
}
switch (this.method) {
switch (this.getMethod()) {
case "GET":
this._interface.send();
break;
default:
this._interface.send(this.serialize());
this._interface.send(this.serialize(target_url));
}
// Waiting a response
@ -628,148 +601,144 @@ var HTTPObject = function(engine) {
// Get response text
responseText = this._interface.responseText;
} else if (this.engine == "CURL") {
if (this.states.length > 0) {
// Make CURL context
var state = this.states[this.states.length - 1];
var cmd = [];
var url = this.getProxiedURL(state.url);
// Build the cURL command line context
var cmd = [];
if (this.isDebugging) {
cmd.push("-v");
}
if (this.isCompressedResponse) {
cmd.push("--compressed");
}
if (this.isFollowRedirect) {
cmd.push("-L");
}
cmd.push("-X");
cmd.push(this.method);
if (Object.keys(this.headers).length > 0) {
for (var key in this.headers) {
var value = this.evaluate(this.headers[key]);
if (value != null) {
cmd.push("-H");
cmd.push(key + ": " + value);
}
}
}
if (this.cookie != null) {
cmd.push("-b");
cmd.push(this.evaluate(this.cookie));
}
if (this.isLoggingCookie) {
cmd.push("-c");
cmd.push(this.storedCookie.path);
}
cmd.push("-A");
cmd.push(this.evaluate(this.userAgent));
// --connect-timeout
if (this.connectTimeout > 0) {
cmd.push("--connect-timeout");
cmd.push(this.connectTimeout);
}
// --max-time
if (this.maxTime > 0) {
cmd.push("--max-time");
cmd.push(this.maxTime);
}
// Add the credential parameters
switch (this.credential.method.toUpperCase()) {
case "BASIC":
cmd.push("-u");
cmd.push(this.credential.username + ":" + this.credential.password);
break;
}
// Add the request body if this is not GET method
if (this.method !== "GET") {
cmd.push("-d");
cmd.push(replaceAndExcludeCaretAnd(this.serialize()));
}
// Add proxy: <[protocol://][user:password@]proxyhost[:port]>
if (this.proxy != null && this.proxy.enabled && this.proxy.type == "stateful") {
cmd.push("-x");
if (this.proxy.credential != null) {
cmd.push([
this.proxy.protocol,
"://",
this.proxy.credential.username,
":",
this.proxy.credential.password,
"@",
this.proxy.host,
":",
this.proxy.port
].join(""));
} else {
cmd.push([
this.proxy.protocol,
"://",
this.proxy.host,
":",
this.proxy.port
].join(""));
}
}
// if it is download
if (this.saveTo != null) {
cmd.push("-o");
cmd.push(this.saveTo);
}
// If not verify SSL
if (!this.isVerifySSL) {
if (this.proxy.enabled) {
cmd.push("--proxy-insecure");
}
cmd.push("-k");
cmd.push("--ssl-no-revoke");
}
// if the count of this.curlOptions greater than 0
if (this.curlOptions.length > 0) {
cmd = cmd.concat(this.curlOptions);
}
// set the URL
cmd.push(url);
// Get response text
responseText = this._interface.setCharset(this.charset).exec(cmd);
// Reload a cookie in the pipe
if (this.isLoggingCookie) {
this.storedCookie.reload();
}
// If enabled the charset(text encoding) detector
if (this.isUseDetectCharset) {
var detectedCharset = this.detectCharset(responseText);
console.log("Detected charset:", detectedCharset);
if (detectedCharset != null && this.charset != detectedCharset) {
var _interface = SHELL.create();
responseText = _interface.setCharset(detectedCharset).exec(cmd);
debuggingText = _interface.stderr.read();
}
}
// Get debuging text
debuggingText = this._interface.stderr.read();
if (this.isDebugging) {
cmd.push("-v");
}
if (this.isCompressedResponse) {
cmd.push("--compressed");
}
if (this.isFollowRedirect) {
cmd.push("-L");
}
cmd.push("-X");
cmd.push(this.getMethod());
if (Object.keys(this.headers).length > 0) {
for (var key in this.headers) {
var value = this.evaluate(this.headers[key]);
if (value != null) {
cmd.push("-H");
cmd.push(key + ": " + value);
}
}
}
if (this.cookie != null) {
cmd.push("-b");
cmd.push(this.evaluate(this.cookie));
}
if (this.isLoggingCookie) {
cmd.push("-c");
cmd.push(this.storedCookie.path);
}
cmd.push("-A");
cmd.push(this.evaluate(this.getUserAgent()));
// --connect-timeout
if (this.connectTimeout > 0) {
cmd.push("--connect-timeout");
cmd.push(this.connectTimeout);
}
// --max-time
if (this.maxTime > 0) {
cmd.push("--max-time");
cmd.push(this.maxTime);
}
// Add the credential parameters
switch (this.credential.method.toUpperCase()) {
case "BASIC":
cmd.push("-u");
cmd.push(this.credential.username + ":" + this.credential.password);
break;
}
// Add the request body if this is not GET method
if (this.getMethod() !== "GET") {
cmd.push("-d");
cmd.push(replaceAndExcludeCaretAnd(this.serialize(target_url)));
}
// Add proxy: <[protocol://][user:password@]proxyhost[:port]>
if (this.proxy != null && this.proxy.enabled && this.proxy.type == "stateful") {
cmd.push("-x");
if (this.proxy.credential != null) {
cmd.push([
this.proxy.protocol,
"://",
this.proxy.credential.username,
":",
this.proxy.credential.password,
"@",
this.proxy.host,
":",
this.proxy.port
].join(""));
} else {
cmd.push([
this.proxy.protocol,
"://",
this.proxy.host,
":",
this.proxy.port
].join(""));
}
}
// if it is download
if (this.saveTo != null) {
cmd.push("-o");
cmd.push(this.saveTo);
}
// If not verify SSL
if (!this.isVerifySSL) {
if (this.proxy.enabled) {
cmd.push("--proxy-insecure");
}
cmd.push("-k");
cmd.push("--ssl-no-revoke");
}
// if the count of this.curlOptions greater than 0
if (this.curlOptions.length > 0) {
cmd = cmd.concat(this.curlOptions);
}
// set the URL
cmd.push(url);
// Get response text
responseText = this._interface.setCharset(this.charset).exec(cmd);
// Reload a cookie in the pipe
if (this.isLoggingCookie) {
this.storedCookie.reload();
}
// If enabled the charset(text encoding) detector
if (this.isUseDetectCharset) {
var detectedCharset = this.detectCharset(responseText);
console.log("Detected charset:", detectedCharset);
if (detectedCharset != null && this.charset != detectedCharset) {
var _interface = SHELL.create();
responseText = _interface.setCharset(detectedCharset).exec(cmd);
debuggingText = _interface.stderr.read();
}
}
// Get debuging text
debuggingText = this._interface.stderr.read();
// clear manually
this._interface.clear();
@ -778,10 +747,10 @@ var HTTPObject = function(engine) {
var job_priority = "normal";
var state = this.states[this.states.length - 1];
var cmd = ["/transfer", job_name];
var url = this.getProxiedURL(state.url);
var url = this.getProxiedUrl(state.url);
var out = PipeIPC.connect("volatile");
if (this.method == "GET") {
if (this.getMethod() == "GET") {
cmd = cmd.concat(["/download", "/priority", job_priority, url, SYS.getCurrentScriptDirectory() + "\\" + out.path]); // build a BITS command
this._interface.exec(cmd); // launch the download job
out.reload(); // read the downloaded data
@ -795,7 +764,7 @@ var HTTPObject = function(engine) {
} else if (this.engine == "CERT") {
var state = this.states[this.states.length - 1];
var out = PipeIPC.connect("volatile");
var url = this.getProxiedURL(state.url);
var url = this.getProxiedUrl(state.url);
var cmd = ["-urlcache", "-split", "-f", url, out.path];
this._interface.exec(cmd);
out.reload();
@ -818,9 +787,14 @@ var HTTPObject = function(engine) {
if (this.isJSONResponse()) {
try {
this.setResponseBody(JSON.parse(responseText));
var res = JSON.parse(responseText);
if (this.proxy.type == "stateless-jsonrpc2") {
this.setResponseBody(res.result.data);
} else {
this.setResponseBody(res);
}
} catch (e) {
console.error("JSON parse error: " + e.message);
console.error("JSON parse error:", e.message);
this.setResponseBody({});
}
} else {
@ -1217,6 +1191,25 @@ function parseURL(url) {
};
}
// Check an available proxies
AVAILABLE_PROXIES.forEach(function(proxy) {
if (proxy.type == "file") {
if (FILE.fileExists(proxy.url)) {
try {
var fileContents = FILE.readFile(proxy.url, FILE.CdoCharset.CdoUTF_8);
var data = JSON.parse(fileContents);
data.forEach(function(x) {
AVAILABLE_PROXIES.push(x);
});
} catch (e) {
console.warn(proxy.url, "is not a valid file");
}
} else {
console.warn(proxy.url, "does not exists");
}
}
});
exports.create = create;
exports.get = get;
exports.post = post;
@ -1228,7 +1221,7 @@ exports.parseURL = parseURL;
exports.DEFAULT_USER_AGENT = DEFAULT_USER_AGENT;
exports.defaultUserAgent = DEFAULT_USER_AGENT; // compatible
exports.VERSIONINFO = "HTTP REST Client (http.js) version 0.7.40";
exports.VERSIONINFO = "WelsonJS framework HTTP client (http.js) version 0.7.48";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;

32
lib/ip-reputation.js Normal file
View File

@ -0,0 +1,32 @@
// ip-reputation.js
// Namhyeon Go <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
//
// ***SECURITY NOTICE***
// IP Reputation Checker requires an internet connection, and data may be transmitted externally. Users must adhere to the terms of use and privacy policy.
// - AbuseIPDB website: https://www.abuseipdb.com/
//
var HTTP = require("lib/http");
var APIKEY = require("lib/apikey");
function check(ip_address) {
var apikey = APIKEY.getApiKey("abuseipdb");
var response = HTTP.create()
.setHeaders({
"Key": apikey,
"Accept": "application/json"
})
.setParameters({
"ipAddress": ip_address
});
return response.responseBody;
}
exports.check = check;
exports.VERSIONINFO = "IP Reputation Checker (ip-reputation.js) version 0.1";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;

View File

@ -2,18 +2,18 @@
// JSON-RPC 2.0 wrapper for WelsonJS framework
// Namhyeon Go <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
var HTTP = require("lib/http");
function jsonrpc2(url) {
//
function JsonRpc2(url) {
this.url = url;
this.userAgent = "php-httpproxy/0.1.5 (Client; WelsonJS; abuse@catswords.net)";
this.userAgent = "php-httpproxy/0.1.5 (Client; WelsonJS)";
this.setUserAgent = function(agent) {
this.userAgent = agent;
};
this.invoke = function(method, params, id) {
var result;
var response = HTTP.create("MSXML")
var response = require("lib/http").create("MSXML")
.setContentType("application/json")
.setDataType("json")
.setUserAgent(this.userAgent)
@ -46,13 +46,17 @@ function wrap(method, params, id) {
}
function create(url) {
return new jsonrpc2(url);
return new JsonRpc2(url);
}
var DEFAULT_JSONRPC2_URL = "https://azure-ashlan-40.tiiny.io/";
exports.wrap = wrap;
exports.create = create;
exports.VERSIONINFO = "JSON-RPC 2.0 wrapper (jsonrpc2.js) version 0.1.4";
exports.DEFAULT_JSONRPC2_URL = DEFAULT_JSONRPC2_URL;
exports.VERSIONINFO = "JSON-RPC 2.0 wrapper (jsonrpc2.js) version 0.1.5";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;

View File

@ -0,0 +1,539 @@
// language-inference-engine.js
// Language Inference Engine (e.g., NLP, LLM) services integration
// Namhyeon Go <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
// ***SECURITY NOTICE***
// Language Inference Engine requires an internet connection, and data may be transmitted externally. Users must adhere to the terms of use and privacy policy.
// - OpenAI: https://openai.com/policies/row-privacy-policy/
// - Anthropic: https://www.anthropic.com/legal/privacy
// - Groq: https://groq.com/privacy-policy/
// - Mistral: https://mistral.ai/terms/
// - xAI: https://x.ai/legal/privacy-policy
// - Google Gemini: https://developers.google.com/idx/support/privacy
// - DeepSeek: https://chat.deepseek.com/downloads/DeepSeek%20Privacy%20Policy.html
// - Moonshot: https://kimi.moonshot.cn/user/agreement/userPrivacy
// - AlibabaCloud: https://www.alibabacloud.com/help/en/legal/latest/alibaba-cloud-international-website-privacy-policy
// - ClovaStudio: https://clova-x.naver.com/ai_policies
// - Catswords AI: https://policy.catswords.social/site_terms.html
//
var HTTP = require("lib/http");
var CRED = require("lib/credentials");
var BIAS_MESSAGE = "Write all future code examples in JavaScript ES3 using the exports variable. " +
"Include a test method with the fixed name test. " +
"Respond exclusively in code without blocks.";
var ENGINE_PROFILES = {
"openai": {
"type": "llm",
"availableModels": [
"gpt-4o-mini",
"gpt-4o",
"o1",
"o1-mini",
"o3-mini",
"gpt-4-turbo",
"gpt-3.5-turbo"
],
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer {apikey}"
},
"url": "https://api.openai.com/v1/chat/completions",
"wrap": function(model, message, temperature) {
return {
"model": model,
"messages": [{
"role": "developer",
"content": BIAS_MESSAGE
}, {
"role": "user",
"content": message
}],
"temperature": temperature,
"stream": false
};
},
"callback": function(response) {
if ("error" in response) {
return ["Error: " + response.error.message];
} else {
return response.choices.reduce(function(a, x) {
a.push(x.message.content);
return a;
}, []);
}
}
},
"anthropic": {
"type": "llm",
"availableModels": [
"claude-3-5-sonnet-20241022"
],
"headers": {
"Content-Type": "application/json",
"x-api-key": "{apikey}",
"anthropic-version": "2023-06-01"
},
"url": "https://api.anthropic.com/v1/messages",
"wrap": function(model, message, temperature) {
return {
"model": model,
"messages": [
{
"role": "system",
"content": BIAS_MESSAGE
},
{
"role": "user",
"content": message
}
],
"temperature": temperature,
"stream": false
};
},
"callback": function(response) {
if ("error" in response) {
return ["Error: " + response.error.message];
} else {
return response.content.reduce(function(a, x) {
if (x.type == "text") {
a.push(x.text);
} else {
a.push("Not supported type: " + x.type);
}
return a;
}, []);
}
}
},
"groq": {
"type": "llm",
"availableModels": [
"llama-3.1-8b-instant"
],
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer {apikey}"
},
"url": "https://api.groq.com/openai/v1/chat/completions",
"wrap": function(model, message, temperature) {
return {
"model": model,
"messages": [
{
"role": "system",
"content": BIAS_MESSAGE
},
{
"role": "user",
"content": message
}
],
"temperature": temperature,
"stream": false
};
},
"callback": function(response) {
if ("error" in response) {
return ["Error: " + response.error.message];
} else {
return response.choices.reduce(function(a, x) {
a.push(x.message.content);
return a;
}, []);
}
}
},
"xai": {
"type": "llm",
"availableModels": [
"grok-2-latest"
],
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer {apikey}"
},
"url": "https://api.x.ai/v1/chat/completions",
"wrap": function(model, message, temperature) {
return {
"model": model,
"messages": [
{
"role": "system",
"content": BIAS_MESSAGE
},
{
"role": "user",
"content": message
}
],
"temperature": temperature,
"stream": false
};
},
"callback": function(response) {
return response.choices.reduce(function(a, x) {
a.push(x.message.content);
return a;
}, []);
}
},
"google": {
"type": "llm",
"availableModels": [
"gemini-1.5-flash"
],
"headers": {
"Content-Type": "application/json"
},
"url": "https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent?key={apikey}",
"warp": function(model, message, temperature) {
return {
"contents": [
{
"parts": [
{
"text": message
}
]
}
]
};
},
"callback": function(response) {
if ("error" in response) {
return ["Error: " + response.error.message];
} else {
return response.candidates.reduce(function(a, x) {
x.content.parts.forEach(function(part) {
if ("text" in part) {
a.push(part.text);
} else {
a.push("Not supported type");
}
});
return a;
}, []);
}
}
},
"mistral": {
"type": "llm",
"availableModels": [
"ministral-8b-latest"
],
"url": "https://api.mistral.ai/v1/chat/completions",
"wrap": function(model, message, temperature) {
return {
"model": model,
"messages": [
{
"role": "system",
"content": BIAS_MESSAGE
},
{
"role": "user",
"content": message
}
],
"temperature": temperature,
"stream": false
};
},
"callback": function(response) {
if ("error" in response) {
return ["Error: " + response.error.message];
} else {
return response.choices.reduce(function(a, x) {
a.push(x.message.content);
return a;
}, []);
}
}
},
"deepseek": {
"type": "llm",
"availableModels": [
"deepseek-chat"
],
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer {apikey}"
},
"url": "https://api.deepseek.com/chat/completions",
"wrap": function(model, message, temperature) {
return {
"model": model,
"messages": [
{
"role": "system",
"content": BIAS_MESSAGE
},
{
"role": "user",
"content": message
}
],
"temperature": temperature,
"stream": false
};
},
"callback": function(response) {
if ("error" in response) {
return ["Error: " + response.error.message];
} else {
return response.choices.reduce(function(a, x) {
a.push(x.message.content);
return a;
}, []);
}
}
},
"moonshot": {
"type": "llm",
"availableModels": [
"moonshot-v1-8k"
],
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer {apikey}"
},
"url": "https://api.moonshot.cn/v1",
"wrap": function(model, message, temperature) {
return {
"model": model,
"messages": [
{
"role": "system",
"content": BIAS_MESSAGE
},
{
"role": "user",
"content": message
}
],
"temperature": temperature,
"stream": false
};
},
"callback": function(response) {
if ("error" in response) {
return ["Error: " + response.error.message];
} else {
return response.choices.reduce(function(a, x) {
a.push(x.message.content);
return a;
}, []);
}
}
},
"clovastudio": {
"type": "llm",
"availableModels": [
"HCX-003",
"HCX-DASH-001"
],
"headers": {
"Authorization": "Bearer {apikey}",
"NCP-CLOVASTUDIO-REQUEST-ID": "",
"Content-Type": "application/json",
"Accept": "application/json"
},
"url": "https://clovastudio.stream.ntruss.com/testapp/v1/chat-completions/{model}",
"wrap": function(model, message, temperature) {
return {
"topK": 0,
"includeAiFilters": true,
"maxTokens": 4096,
"temperature": temperature,
"messages": [
{
"role": "system",
"content": BIAS_MESSAGE
},
{
"role": "user",
"content": message
}
],
"stopBefore": [],
"repeatPenalty": 5.0,
"topP": 0.8
};
},
"callback": function(response) {
if (response.status.code != "20000") {
return ["Error: " + response.status.message];
} else {
return [response.result.message];
}
}
},
"alibabacloud": {
"type": "llm",
"availableModels": [
"qwen-plus",
"qwen-max",
"qwen-turbo"
],
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer {apikey}"
},
"url": "https://dashscope-intl.aliyuncs.com/compatible-mode/v1/chat/completions",
"wrap": function(model, message, temperature) {
return {
"model": model,
"messages": [
{
"role": "system",
"content": BIAS_MESSAGE
},
{
"role": "user",
"content": message
}
],
"temperature": temperature,
"stream": false
};
},
"callback": function(response) {
if ("error" in response) {
return ["Error: " + response.error.message];
} else {
return response.choices.reduce(function(a, x) {
a.push(x.message.content);
return a;
}, []);
}
}
},
"catswords-ai": {
"type": "llm",
"availableModels": [
"openchat-3.5-0106",
"qwen1.5-14b-chat-awq",
"gemma-7b-it",
"una-cybertron-7b-v2-bf16",
"starling-lm-7b-beta",
"hermes-2-pro-mistral-7b"
],
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer {apikey}"
},
"url": "https://ai.catswords.net",
"wrap": function(model, message, temperature) {
return {
"model": model,
"messages": [
{
"role": "system",
"content": BIAS_MESSAGE
},
{
"role": "user",
"content": message
}
],
"temperature": temperature,
"stream": false
};
},
"callback": function(response) {
if ("error" in response) {
return ["Error: " + response.error.message];
} else {
return response.choices.reduce(function(a, x) {
a.push(x.message.content);
return a;
}, []);
}
}
}
};
function LanguageInferenceEngine() {
this.type = ""; // e.g. legacy (Legacy NLP), LLM based AI (LLM)
this.provider = "";
this.model = "";
this.engineProfile = null;
this.setProvider = function(provider) {
this.provider = provider;
if (this.provider in ENGINE_PROFILES) {
this.engineProfile = ENGINE_PROFILES[provider];
this.type = this.engineProfile.type;
this.model = this.engineProfile.availableModels[0];
}
return this;
};
this.setModel = function(model) {
this.model = model;
return this;
};
this.setEngineProfileURL = function(url) {
if (this.engineProfile == null)
return this;
this.engineProfile.url = url;
return this;
}
this.inference = function(message, temperature) {
if (this.engineProfile == null)
return this;
var apikey = CRED.get("apikey", this.provider); // Get API key
var headers = this.engineProfile.headers;
var wrap = this.engineProfile.wrap;
var url = this.engineProfile.url;
var callback = this.engineProfile.callback;
var response = HTTP.create("MSXML")
.setVariables({
"apikey": apikey
})
.setHeaders(headers)
.setRequestBody(wrap(this.model, message, temperature))
.open("post", url)
.send()
.responseBody;
return callback(response);
};
}
exports.setBiasMessage = function(biasMessage) {
BIAS_MESSAGE = biasMessage;
};
exports.LanguageInferenceEngine = LanguageInferenceEngine;
exports.create = function() {
return new LanguageInferenceEngine();
};
exports.VERSIONINFO = "Language Inference Engine integration version 0.1.11";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;

71
lib/ovftool.js Normal file
View File

@ -0,0 +1,71 @@
// ovftool.js
// Namhyeon Go <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
//
// Download OVFTool (Open Virtualization Format (OVF) Tool):
// https://developer.broadcom.com/tools/open-virtualization-format-ovf-tool/latest
//
var SHELL = require("lib/shell");
var CRED = require("lib/credentials");
function OVFObject() {
this.binPath = "bin\\x64\\VMware-ovftool-4.6.3-24031167-win.x86_64\\ovftool\\ovftool.exe";
this.hostname = "";
this.port = 443;
this.resourceName = "";
this.setBinPath = function(binPath) {
this.binPath = binPath;
};
this.setHostName = function(hostname) {
this.hostname = hostname;
};
this.setPort = function(port) {
this.port = port;
};
this.setResourceName = function(resourceName) {
this.resourceName = resourceName;
};
this.saveTo = function(filename) {
var cred = CRED.get("password", "ovftool");
var connectionString = "vi://" +
encodeURIComponent(cred.username) + ":" +
encodeURIComponent(cred.password) + "@" +
this.hostname + (this.port == 443 ? "" : ":" + this.port) +
this.resourceName
;
var cmd = [
this.binPath,
connectionString,
filename
];
console.log("Use this connection string:", connectionString);
// run the command synchronously
SHELL.show(cmd, false);
};
}
function setCredential(username, password) {
CRED.push("password", "ovftool", {
"username": username,
"password": password
});
}
function create() {
return new OVFObject();
}
exports.setCredential = setCredential;
exports.create = create;
exports.VERSIONINFO = "Broadcom/VMware OVF Tool interface (ovftool.js) version 0.1.2";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;

View File

@ -1,11 +1,48 @@
var Py3 = require("lib/python3");
// punycode.js
// Namhyeon Go <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
//
// ***SECURITY NOTICE***
// Due to potential security issues, the Public API URL is not provided. If you need to request access, please refer to the project's contact information.
// You can download the server-side script that implements this functionality from the link below:
// https://github.com/gnh1201/caterpillar
//
var JsonRpc2 = require("lib/jsonrpc2");
function encode(s) {
return Py3.execScript("app\\assets\\py\\idnaencode.py", [s]).trim();
var rpc = JsonRpc2.create(JsonRpc2.DEFAULT_JSONRPC2_URL);
var result = rpc.invoke("relay_invoke_method", {
"callback": "load_script",
"requires": [
"https://scriptas.catswords.net/punycode.class.php"
],
"args": [
"return Punycode::encodeHostname('" + s + "')"
]
}, "");
return result.data;
}
function decode(s) {
var rpc = JsonRpc2.create(JsonRpc2.DEFAULT_JSONRPC2_URL);
var result = rpc.invoke("relay_invoke_method", {
"callback": "load_script",
"requires": [
"https://scriptas.catswords.net/punycode.class.php"
],
"args": [
"return Punycode::decodeHostname('" + s + "')"
]
}, "");
return result.data;
}
exports.encode = encode;
exports.decode = decode;
exports.VERSIONINFO = "Punycode Converter (punycode.js) version 0.1";
exports.VERSIONINFO = "Punycode Conversion Client (punycode.js) version 0.2.4";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;

View File

@ -1,23 +1,44 @@
// python3.js
// Python Interface
// Namhyeon Go (Catswords Research) <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
var SYS = require("lib/system");
var SHELL = require("lib/shell");
function PythonObject(platform) {
this.version = "3.10.2-embed";
this.platform = platform;
function PythonObject() {
this.binPath = null;
this.version = "3.13.2";
this.create = function() {
var arch = SYS.getArch();
if (arch.toLowerCase().indexOf("arm") > -1) {
this.setBinPath("bin\\arm64\\python-" + this.version + "-embed-arm64\\python.exe");
} else if (arch.indexOf("64") > -1) {
this.setBinPath("bin\\x64\\python-" + this.version + "-embed-amd64\\python.exe");
} else {
this.setBinPath("bin\\x86\\python-" + this.version + "-embed-win32\\python.exe");
}
};
this.setBinPath = function(binPath) {
this.binPath = binPath;
};
this.setVersion = function(version) {
this.version = version;
this.create();
};
this.execScript = function(scriptName, args) {
return SHELL.exec([
"bin\\python-" + this.version + "\\" + this.platform + "\\python",
this.binPath,
scriptName
].concat(args));
};
this.runScript = function(scriptName, args) {
return SHELL.show([
"bin\\python-" + this.version + "\\" + this.platform + "\\python",
this.binPath,
scriptName
].concat(args));
};
@ -25,15 +46,14 @@ function PythonObject(platform) {
exports.PythonObject = PythonObject;
exports.create = function(platform) {
var platform = (typeof platform !== "undefined" ? platform : "amd64");
return new PythonObject(platform);
exports.create = function() {
return new PythonObject();
};
exports.execScript = function(scriptName, args) {
return (new PythonObject()).execScript(scriptName, args);
};
exports.VERSIONINFO = "Python Interface (python3.js) version 0.2";
exports.VERSIONINFO = "Python Interface (python3.js) version 0.2.1";
exports.global = global;
exports.require = global.require;

View File

@ -1,6 +1,8 @@
// router.js
// Content-Type based URI router for WelsonJS framework
// Namhyeon Go <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
//
function RouteModel(path, callback) {
this.path = path;
this.callback = callback;
@ -8,32 +10,84 @@ function RouteModel(path, callback) {
function RouterObject() {
var routes = [];
var renders = [];
this.render = function(filename, data) {};
this.setRender = function(render) {
this.render = render;
this.setRender = function(callback, contentType) {
var contentType = (typeof contentType !== "undefined" ?
contentType : ""
);
renders.push({
"contentType": contentType,
"callback": callback
});
};
this.render = function(uri, data) {
// Use expression: data:application/json,%7B%22key%22%3A%22value%22%7D
// Use expression: data:text/html,%3Ch1%3EHello%3C%2Fh1%3E
// Use expression: /path/to/file.html
var contents = (function(uri, start, end) {
if (start > -1 && end > start) {
return [uri.substring(start, end), uri.substring(end + 1)];
}
return ["", uri];
})(uri, uri.indexOf("data:"), uri.indexOf(','));
var contentType = contents[0];
var rawData = (contentType != "" ?
decodeURIComponent(contents[1]) : contents[1]
);
// Multiple renderers are allowed for the same content type. They are executed in the order they were registered.
renders.forEach(function(x) {
if (x.contentType == contentType) {
try {
if (typeof x.callback === "function") {
x.callback(rawData, data);
} else {
console.warn("Failed to render content of type " + x.contentType, "Not a function");
}
} catch (e) {
console.warn("Failed to render content of type " + x.contentType, e.message);
}
}
});
};
this.add = function(path, callback) {
routes.push(new RouteModel(path, callback));
};
this.go = function(path) {
this.go = function(uri) {
var path = uri.split(/[?#]/)[0];
var model = routes.find(function(x) {
return (x.path == path);
return path === x.path || path.indexOf(x.path + "/") === 0;
});
if (typeof model !== "undefined") {
//try {
model.callback(this.render);
//} catch (e) {
// console.error(path, e.message);
//}
if (!model) {
console.error("No matching route found for:", uri);
return;
}
if (typeof model.callback !== "function") {
console.error("Invalid callback for route:", model.path);
return;
}
try {
model.callback(this.render);
} catch (e) {
console.error("Error executing callback for route:", model.path, e.message);
}
};
}
exports.Router = new RouterObject();
exports.VERSIONINFO = "URI Router (router.js) version 0.1.1";
exports.VERSIONINFO = "Content-Type based URI router (router.js) version 0.1.2";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;

64
lib/serp.js Normal file
View File

@ -0,0 +1,64 @@
// serp.js
// SERP/SEO tools integration for WelsonJS framework
// Namhyeon Go <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
function parseUrl(url) {
var getEngine = function(url) {
var defaultEngine = "google";
var engines = {
"google": ["naver", "daum"],
"google_shopping": [
"aliexpress", "temu", "coupang", "shopping.naver",
"ssg", "gmarket", "11st", "store.kakao",
"lotteon", "tmon", "wemakeprice"
],
"default": [
"google", "youtube", "bing", "baidu",
"amazon", "duckduckgo"
]
};
var match = url.match(/^(?:https?:\/\/)?(?:www\.)?([\w.-]+)\.\w+$/);
if (!match) {
return defaultEngine;
}
var domain = match[1];
for (var key in engines) {
if (engines.hasOwnProperty(key)) {
var group = engines[key];
if (group.indexOf(domain) !== -1) {
if (key === "default") {
return domain;
}
return key;
}
}
}
return defaultEngine;
};
var getKeyword = function(url) {
var regex = /[?&](q|wd|query|keyword|search_query|k|SearchText|search_key)=([^&]*)/g;
//var regex = /(?:[?&](q|wd|keyword|query|search_query|k|SearchText|search_key)=|\/pdsearch\/)([^&?]*)/g;
var match, keywords = [];
while ((match = regex.exec(url)) !== null) {
keywords.push(match[2]);
}
return keywords.join(' ');
};
return {
"engine": getEngine(url),
"keyword": getKeyword(url)
}
};
exports.parseUrl = parseUrl;
exports.VERSIONINFO = "SERP/SEO tools integration (serp.js) version 0.1";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;

View File

@ -11,7 +11,7 @@ var ShellObject = function() {
this.workingDirectory = null;
this.isElevated = false;
this.isFork = false;
this.isVisibleWindow = false;
this.visibility = "hidden";
this.isPreventClear = false;
this.charset = PipeIPC.CdoUS_ASCII;
@ -53,12 +53,22 @@ var ShellObject = function() {
}
return this;
};
this.setVisibleWindow = function(visible) {
this.isVisibleWindow = visible;
this.setVisibility = function(visibility) {
this.visibility = visibility;
return this;
};
// @deprecated
this.setVisibleWindow = function(visible) {
if (visible == false) {
this.setVisibility("hidden");
} else {
this.setVisibility("visible");
}
return this;
};
this.build = function(cmd) {
var prefix = this.prefix;
var wrap = function(s) {
@ -136,18 +146,26 @@ var ShellObject = function() {
this.run = function(cmd, fork) {
var fork = (typeof(fork) !== "undefined") ? fork : true;
var c = "%comspec% /q /c (" + this.build(cmd) + ")";
var windowStyle = (this.visibility === "hidden" ? 0 : 1);
console.log("ShellObject.run() ->", c);
this._interface.Run(c, (!this.isVisibleWindow ? 0 : 1), !fork);
if (windowStyle == 1) {
console.log("Will be open the visible window");
}
this._interface.Run(c, windowStyle, !fork);
};
this.runAs = function(FN, args) {
var oShell = CreateObject("Shell.Application");
var windowStyle = (this.visibility === "hidden" ? 0 : 1);
var _args = null;
console.log("ShellObject.runAs() ->", FN);
if (typeof(args) !== "undefined") {
_args = args.join(' ');
}
oShell.shellExecute(FN, _args, this.workingDirectory, "runas", (!this.isVisibleWindow ? 0 : 1));
if (windowStyle == 1) {
console.log("Will be open the visible window");
}
oShell.shellExecute(FN, _args, this.workingDirectory, "runas", windowStyle);
return oShell;
};
@ -205,7 +223,7 @@ exports.run = function(cmd, fork) {
};
exports.show = function(cmd, fork) {
return (new ShellObject()).setVisibleWindow(true).run(cmd, fork);
return (new ShellObject()).setVisibility("visible").run(cmd, fork);
};
exports.runAs = function(FN, args) {
@ -213,7 +231,7 @@ exports.runAs = function(FN, args) {
};
exports.showAs = function(FN, args) {
return (new ShellObject()).setVisibleWindow(true).runAs(FN, args);
return (new ShellObject()).setVisibility("visible").runAs(FN, args);
};
exports.createProcess = function(cmd, workingDirectory) {
@ -236,7 +254,7 @@ exports.getPathOfMyDocuments = function() {
exports.CdoCharset = PipeIPC.CdoCharset;
exports.VERSIONINFO = "Windows Shell Interface (shell.js) version 0.3.15";
exports.VERSIONINFO = "Windows Shell Interface (shell.js) version 0.3.18";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;

View File

@ -1,8 +1,8 @@
// std.js
// Common routines
// WelsonJS Standard Library
// Namhyeon Go <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
//
// Polyfills
if (!Function.prototype.GetResource) {
Function.prototype.GetResource = function(ResourceName) {
@ -55,6 +55,7 @@ if (typeof Enumerator !== "undefined") {
result.push(itemObject);
this.moveNext();
}
return result;
};
}
@ -255,16 +256,49 @@ function alert(message) {
if (typeof window !== "undefined") {
window.alert(message);
} else {
CreateObject("WScript.Shell").Popup(message);
try {
CreateObject("WScript.Shell").Popup(message, 0, "WelsonJS", 0);
} catch (e) {
console.error(e.message);
}
}
}
function confirm(message) {
var result;
if (typeof window !== "undefined") {
return window.confirm(message);
result = window.confirm(message);
} else {
CreateObject("WScript.Shell").Popup(message);
try {
result = (CreateObject("WScript.Shell").Popup(message, 0, "WelsonJS", 4) == 6);
} catch (e) {
console.error(e.message);
result = false;
}
}
return result;
}
function prompt(message, _default) {
var result;
if (typeof window !== "undefined") {
result = window.prompt(message);
} else {
try {
result = CreateObject("WelsonJS.Toolkit").Prompt(message);
} catch (e) {
console.error(e.message);
if (typeof _default !== "undefined") {
result = _default;
console.warn("Use default value:", _default);
}
}
}
return result;
}
function parseEnv(s) {
@ -551,8 +585,9 @@ exports.Storage = StdStorage;
exports.alert = alert;
exports.confirm = confirm;
exports.prompt = prompt;
exports.VERSIONINFO = "WelsonJS Standard Library (std.js) version 0.8.12";
exports.VERSIONINFO = "WelsonJS Standard Library (std.js) version 0.8.16";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;

97
lib/task-scheduler.js Normal file
View File

@ -0,0 +1,97 @@
// task-scheduler.js
// https://github.com/gnh1201/welsonjs
// Connect to Task Scheduler service
function connect() {
var service = CreateObject("Schedule.Service");
service.Connect();
return service;
}
// Get the root folder of Task Scheduler
function getRootFolder(service) {
return service.GetFolder("\\");
}
// Create a new task definition
function createTaskDefinition(service) {
return service.NewTask(0); // Flags = 0
}
// Set registration info for the task
function setRegistrationInfo(taskDefinition, description, author) {
var regInfo = taskDefinition.RegistrationInfo;
regInfo.Description = description;
regInfo.Author = author;
}
// Configure task settings
function configureTaskSettings(taskDefinition) {
var settings = taskDefinition.Settings;
settings.StartWhenAvailable = true;
}
// Create a registration trigger
function createRegistrationTrigger(taskDefinition) {
var triggers = taskDefinition.Triggers;
var trigger = triggers.Create(7); // 7 = Registration Trigger
trigger.ExecutionTimeLimit = "PT5M"; // Five minutes
trigger.Id = "RegistrationTriggerId";
}
// Add an action to execute a program
function addExecutableAction(taskDefinition, executablePath) {
var actions = taskDefinition.Actions;
var action = actions.Create(0); // 0 = Executable Action
action.Path = executablePath;
}
// Register the task in Task Scheduler
function registerTask(rootFolder, taskDefinition, taskName) {
rootFolder.RegisterTaskDefinition(
taskName,
taskDefinition,
6, // Task creation flags
null, // UserId
null, // Password
3 // LogonType
);
}
// Create and register the task
function createAndRegisterTask(service, rootFolder, taskName, executablePath, description, author) {
var taskDefinition = createTaskDefinition(service);
setRegistrationInfo(taskDefinition, description, author);
configureTaskSettings(taskDefinition);
createRegistrationTrigger(taskDefinition);
addExecutableAction(taskDefinition, executablePath);
console.log("Task definition created. About to submit the task...");
registerTask(rootFolder, taskDefinition, taskName);
console.log("Task submitted.");
}
function test() {
var service = connectToService();
var rootFolder = getRootFolder(service);
createAndRegisterTask(
service,
rootFolder,
"Test Registration Trigger",
"C:\\Windows\\System32\\notepad.exe",
"Start Notepad when the task is registered.",
"Author Name"
);
}
exports.connect = connect;
exports.getRootFolder = getRootFolder;
exports.createAndRegisterTask = createAndRegisterTask;
exports.test = test;
exports.VERSIONINFO = "Windows Task Scheduler Scripting Interface (task-scheduler.js) version 0.1";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = require;

56
lib/totp.js Normal file
View File

@ -0,0 +1,56 @@
// totp.js
// TOTP library for WelsonJS framework
// Namhyeon Go <abuse@catswords.net>
// https://github.com/gnh1201/welsonjs
//
// ***SECURITY NOTICE***
// Due to potential security issues, the Public API URL is not provided. If you need to request access, please refer to the project's contact information.
// You can download the server-side script that implements this functionality from the link below:
// https://github.com/gnh1201/caterpillar
//
var JsonRpc2 = require("lib/jsonrpc2");
function getPubKey() {
var rpc = JsonRpc2.create(JsonRpc2.DEFAULT_JSONRPC2_URL);
var result = rpc.invoke("relay_invoke_method", {
"callback": "load_script",
"requires": [
"https://scriptas.catswords.net/class.tfa.php"
],
"args": [
"$tfa = new tfa(); return $tfa->getPubKey()"
]
}, "");
return result.data;
}
function getOtp(pubkey) {
var rpc = JsonRpc2.create(JsonRpc2.DEFAULT_JSONRPC2_URL);
var result = rpc.invoke("relay_invoke_method", {
"callback": "load_script",
"requires": [
"https://scriptas.catswords.net/class.tfa.php"
],
"args": [
"$tfa = new tfa(); return $tfa->getOtp('" + pubkey + "')"
]
}, "");
return result.data;
}
exports.getPubKey = getPubKey;
exports.getOtp = getOtp;
exports.VERSIONINFO = "TOTP Client (totp.js) version 0.1.8";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;
/*
// Example:
var TOTP = require("lib/totp");
console.log(TOTP.getPubKey()); // get public key. e.g. 6Y4R 3AQN 4TTV CEQT
console.log(TOTP.getOtp('6Y4R 3AQN 4TTV CEQT')); // get OTP code. e.g. 317884
*/

View File

@ -1,5 +1,5 @@
; @created_on 2020-06-26
; @updated_on 2024-07-30
; @updated_on 2025-03-21
; @author Namhyeon Go (Catswords Research) <abuse@catswords.net>
[Setup]
@ -7,7 +7,7 @@ AppName=WelsonJS
AppVersion=0.2.7
WizardStyle=modern
; DefaultDirName={pf}\{cm:AppName}
DefaultDirName={commonpf}\{cm:AppName}
DefaultDirName={commonpf32}\{cm:AppName}
DefaultGroupName={cm:AppName}
; UninstallDisplayIcon={app}\UnInst.exe
UninstallDisplayIcon={app}\unins000.exe
@ -15,7 +15,7 @@ Compression=lzma2
SolidCompression=yes
OutputDir=bin\installer
PrivilegesRequired=admin
ArchitecturesInstallIn64BitMode=x64
; ArchitecturesInstallIn64BitMode=x64
RestartIfNeededByRun=no
DisableStartupPrompt=true
DisableFinishedPage=true
@ -41,30 +41,42 @@ Source: "*.md"; DestDir: "{app}";
Source: "bootstrap.bat"; DestDir: "{app}";
Source: "uriloader.js"; DestDir: "{app}";
Source: "webloader.js"; DestDir: "{app}";
Source: "testloader.js"; DestDir: "{app}";
Source: "encryptor.js"; DestDir: "{app}";
Source: "bootstrap.js"; DestDir: "{app}";
Source: "scriptcontrol.js"; DestDir: "{app}";
Source: "app\*"; DestDir: "{app}/app"; Flags: ignoreversion recursesubdirs;
Source: "settings.example.ini"; DestDir: "{app}";
Source: "defaultService.example.js"; DestDir: "{app}";
Source: "installService.bat"; DestDir: "{app}";
Source: "uninstallService.bat"; DestDir: "{app}";
Source: "helloworld.*"; DestDir: "{app}";
Source: "app\*"; Excludes: "assets\img\_templates,assets\tessdata\*,assets\tessdata_best\*,assets\tessdata_fast\*"; DestDir: "{app}/app"; Flags: ignoreversion recursesubdirs;
Source: "lib\*"; DestDir: "{app}/lib"; Flags: ignoreversion recursesubdirs;
Source: "bin\*"; DestDir: "{app}/bin"; Flags: ignoreversion recursesubdirs;
Source: "data\*"; DestDir: "{app}/data"; Flags: ignoreversion recursesubdirs;
Source: "bin\*"; Excludes: "installer\*"; DestDir: "{app}/bin"; Flags: ignoreversion recursesubdirs;
Source: "data\*"; Excludes: "*-apikey.txt"; DestDir: "{app}/data"; Flags: ignoreversion recursesubdirs;
; Source: "node_modules\*"; DestDir: "{app}/node_modules"; Flags: ignoreversion recursesubdirs;
; Source: "bower_components\*"; DestDir: "{app}/node_modules"; Flags: ignoreversion recursesubdirs;
[Dirs]
Name: "{app}\tmp";
[InstallDelete]
Type: files; Name: "{app}\settings.ini"
Type: files; Name: "{app}\defaultService.js"
[Icons]
Name: "{group}\Start {cm:AppName}"; Filename: "{app}\bootstrap.bat"; AfterInstall: SetElevationBit('{group}\Start {cm:AppName}.lnk');
Name: "{group}\Start {cm:AppName} Launcher"; Filename: "{app}\bin\x86\WelsonJS.Launcher.exe"; AfterInstall: SetElevationBit('{group}\Start {cm:AppName} Launcher.lnk');
Name: "{group}\Test {cm:AppName}"; Filename: "{app}\bootstrap.bat"; AfterInstall: SetElevationBit('{group}\Test {cm:AppName}.lnk');
Name: "{group}\Uninstall {cm:AppName}"; Filename: "{uninstallexe}"; AfterInstall: SetElevationBit('{group}\Uninstall {cm:AppName}.lnk');
[Run]
; Filename: {app}\bin\gtk2-runtime-2.24.33-2021-01-30-ts-win64.exe;
; Filename: {app}\bin\nmap-7.92\VC_redist.x86.exe;
; Filename: {app}\bin\nmap-7.92\npcap-1.50.exe;
Filename: {app}\installService.bat;
Filename: {app}\bootstrap.bat;
Filename: {app}\installService.bat; Flags: nowait
Filename: {app}\bin\x86\WelsonJS.Launcher.exe; Flags: nowait
[UninstallRun]
Filename: {app}\uninstallService.bat;
; Filename: {code:GetProgramFiles}\GTK2-Runtime Win64\gtk2_runtime_uninst.exe;
; Filename: {code:GetProgramFiles}\Npcap\Uninstall.exe;
; Filename: {app}\bin\nmap-7.92\VC_redist.x86.exe;
@ -110,3 +122,13 @@ begin
if CurUninstallStep = usDone then
ShellExec('open', UninstSiteURL, '', '', SW_SHOW, ewNoWait, ErrorCode);
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssPostInstall then
begin
CopyFile(ExpandConstant('{app}\settings.example.ini'), ExpandConstant('{app}\settings.ini'), False);
CopyFile(ExpandConstant('{app}\defaultService.example.js'), ExpandConstant('{app}\defaultService.js'), False);
end;
end;

View File

@ -824,7 +824,8 @@ var test_implements = {
"Which one does Mom like, and which one does Dad like?",
"If 100 billion won is deposited into my bank account without my knowledge, what would I do?",
"If my friend passed out from drinking, and Arnold Schwarzenegger suggests having a drink together alone, is it okay to ditch my friend and go with him?",
"If there's a snake in our tent during the company camping trip, should I wake up the manager, or should I escape on my own without waking him up?"
"If there's a snake in our tent during the company camping trip, should I wake up the manager, or should I escape on my own without waking him up?",
"queen never cry"
];
// Open the Excel window
@ -1006,10 +1007,11 @@ var test_implements = {
// https://catswords-oss.rdbl.io/5719744820/8278298336
"proxy_custom_provider": function() {
var HTTP = require("lib/http");
var CRED = require("lib/credentials");
var response = HTTP.create()
.setVariables({
"api_key": "YOUR_API_KEY",
"api_key": CRED.get("apikey", "scrapeops"),
"render_js": "false",
"residential": "false",
"country": "us",
@ -1029,10 +1031,11 @@ var test_implements = {
// https://catswords-oss.rdbl.io/5719744820/8278298336
"proxy_serp": function() {
var HTTP = require("lib/http");
var CRED = require("lib/credentials");
var response = HTTP.create()
.setVariables({
"api_key": "YOUR_API_KEY"
"api_key": CRED.get("apikey", "searchapi")
})
.setProxy({
"enabled": true,
@ -1045,6 +1048,23 @@ var test_implements = {
console.log("responseBody:", response.responseBody);
},
"proxy_stateless_jsonrpc2": function() {
var HTTP = require("lib/http");
var response = HTTP.create()
.setProxy({
"enabled": true,
"provider": "github.com/gnh1201/caterpillar",
"type": "stateless-jsonrpc2",
"url": "https://localhost:8080"
})
.setDataType("json")
.open("GET", "https://example.org")
.send();
console.log("responseBody:", response.responseBody);
},
"numbers_test": function() {
// Riemann integrals
console.log("Test Riemann integrals (with 200 subdivisions)");
@ -1095,6 +1115,29 @@ var test_implements = {
console.log(numbers.statistic.standardDev(array));
//console.log(numbers.statistic.randomSample(100, 100, 20));
console.log(numbers.statistic.correlation(array1, array2));
},
"backup_vmware_esxi": function() {
var OVFTool = require("lib/ovftool");
// set the credential (username, and password)
OVFTool.setCredential("arnold", "I_WILL_BE_BACK");
// set target virtual machines
var targetVMs = [
"/MyDatacenter/vm/MyGroup/MyMachine1",
"/MyDatacenter/vm/MyGroup/MyMachine2",
"/MyDatacenter/host/MyGroup/MyMachine2",
"/MyDatacenter/host/MyGroup/MyMachine2"
];
// do backup
targetVMs.forEach(function(resourceName) {
var job = OVFTool.create();
job.setHostName("example.org");
job.setResourceName(resourceName);
job.saveTo("D:\\");
};
}
};

View File

@ -1,3 +1,3 @@
## tmp
A tmp directory is required for the interface of the Shell library.
Some tasks may use the tmp directory if the WelsonJS version is lower than 0.2.7.