commit 3deafe34efca00b5b7100a93fcf0cd6bd99bb7b6
Author: Ylian Saint-Hilaire
Date: Mon Mar 9 11:11:06 2020 -0700
first commit
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..197fccb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,293 @@
+## Ignore nodejs things
+[Ii]mages-branded/
+[Ii]mages-brandedcommander/
+[Ii]mages-isdu
+
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+**/Properties/launchSettings.json
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Typescript v1 declaration files
+typings/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+# CodeRush
+.cr/
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..4667732
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2017-2020 Intel Corporation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/VSSolution.sln b/VSSolution.sln
new file mode 100644
index 0000000..84015b8
--- /dev/null
+++ b/VSSolution.sln
@@ -0,0 +1,38 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.23107.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "Source", ".", "{431BAB2D-8D6E-43E6-B9E9-A7A286AA1CF8}"
+ ProjectSection(WebsiteProperties) = preProject
+ TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.0"
+ Debug.AspNetCompiler.VirtualPath = "/localhost_56807"
+ Debug.AspNetCompiler.PhysicalPath = "..\Source\"
+ Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_56807\"
+ Debug.AspNetCompiler.Updateable = "true"
+ Debug.AspNetCompiler.ForceOverwrite = "true"
+ Debug.AspNetCompiler.FixedNames = "false"
+ Debug.AspNetCompiler.Debug = "True"
+ Release.AspNetCompiler.VirtualPath = "/localhost_56807"
+ Release.AspNetCompiler.PhysicalPath = "..\Source\"
+ Release.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_56807\"
+ Release.AspNetCompiler.Updateable = "true"
+ Release.AspNetCompiler.ForceOverwrite = "true"
+ Release.AspNetCompiler.FixedNames = "false"
+ Release.AspNetCompiler.Debug = "False"
+ VWDPort = "56807"
+ SlnRelativePath = "..\Source\"
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {431BAB2D-8D6E-43E6-B9E9-A7A286AA1CF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {431BAB2D-8D6E-43E6-B9E9-A7A286AA1CF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/agent-desktop-0.0.2.js b/agent-desktop-0.0.2.js
new file mode 100644
index 0000000..2e9f148
--- /dev/null
+++ b/agent-desktop-0.0.2.js
@@ -0,0 +1,781 @@
+/**
+* @description Remote Desktop
+* @author Ylian Saint-Hilaire
+* @version v0.0.2g
+*/
+
+// Construct a MeshServer object
+var CreateAgentRemoteDesktop = function (canvasid, scrolldiv) {
+ var obj = {}
+ obj.CanvasId = canvasid;
+ if (typeof canvasid === 'string') obj.CanvasId = Q(canvasid);
+ obj.Canvas = obj.CanvasId.getContext("2d");
+ obj.scrolldiv = scrolldiv;
+ obj.State = 0;
+ obj.PendingOperations = [];
+ obj.tilesReceived = 0;
+ obj.TilesDrawn = 0;
+ obj.KillDraw = 0;
+ obj.ipad = false;
+ obj.tabletKeyboardVisible = false;
+ obj.LastX = 0;
+ obj.LastY = 0;
+ obj.touchenabled = 0;
+ obj.submenuoffset = 0;
+ obj.touchtimer = null;
+ obj.TouchArray = {};
+ obj.connectmode = 0; // 0 = HTTP, 1 = WebSocket, 2 = WebRTC
+ obj.connectioncount = 0;
+ obj.rotation = 0;
+ obj.protocol = 2; // KVM
+ obj.debugmode = 0;
+ obj.firstUpKeys = [];
+ obj.stopInput = false;
+ obj.localKeyMap = true;
+ obj.altPressed = false;
+ obj.ctrlPressed = false;
+ obj.shiftPressed = false;
+
+ obj.sessionid = 0;
+ obj.username;
+ obj.oldie = false;
+ obj.CompressionLevel = 50;
+ obj.ScalingLevel = 1024;
+ obj.FrameRateTimer = 50;
+ obj.FirstDraw = false;
+
+ obj.ScreenWidth = 960;
+ obj.ScreenHeight = 700;
+ obj.width = 960;
+ obj.height = 960;
+
+ obj.onScreenSizeChange = null;
+ obj.onMessage = null;
+ obj.onConnectCountChanged = null;
+ obj.onDebugMessage = null;
+ obj.onTouchEnabledChanged = null;
+ obj.onDisplayinfo = null;
+ obj.accumulator = null;
+
+ obj.Start = function () {
+ obj.State = 0;
+ obj.accumulator = null;
+ }
+
+ obj.Stop = function () {
+ obj.setRotation(0);
+ obj.UnGrabKeyInput();
+ obj.UnGrabMouseInput();
+ obj.touchenabled = 0;
+ if (obj.onScreenSizeChange != null) obj.onScreenSizeChange(obj, obj.ScreenWidth, obj.ScreenHeight, obj.CanvasId);
+ obj.Canvas.clearRect(0, 0, obj.CanvasId.width, obj.CanvasId.height);
+ }
+
+ obj.xxStateChange = function (newstate) {
+ if (obj.State == newstate) return;
+ obj.State = newstate;
+ obj.CanvasId.style.cursor = 'default';
+ //console.log('xxStateChange', newstate);
+ switch (newstate) {
+ case 0: {
+ // Disconnect
+ obj.Stop();
+ break;
+ }
+ case 3: {
+ // Websocket connected
+
+ break;
+ }
+ }
+ }
+
+ obj.send = function (x) {
+ if (obj.debugmode > 1) { console.log("KSend(" + x.length + "): " + rstr2hex(x)); }
+ if (obj.parent != null) { obj.parent.send(x); }
+ }
+
+ // KVM Control.
+ // Routines for processing incoming packets from the AJAX server, and handling individual messages.
+ obj.ProcessPictureMsg = function (str, X, Y) {
+ //if (obj.targetnode != null) obj.Debug("ProcessPictureMsg " + X + "," + Y + " - " + obj.targetnode.substring(0, 8));
+ var tile = new Image();
+ tile.xcount = obj.tilesReceived++;
+ //console.log('Tile #' + tile.xcount);
+ var r = obj.tilesReceived;
+ tile.src = "data:image/jpeg;base64," + btoa(str.substring(4, str.length));
+ tile.onload = function () {
+ //console.log('DecodeTile #' + this.xcount);
+ if (obj.Canvas != null && obj.KillDraw < r && obj.State != 0) {
+ obj.PendingOperations.push([r, 2, tile, X, Y]);
+ while (obj.DoPendingOperations()) { }
+ }
+ }
+ tile.error = function () { console.log('DecodeTileError'); }
+ }
+
+ obj.DoPendingOperations = function () {
+ if (obj.PendingOperations.length == 0) return false;
+ for (var i = 0; i < obj.PendingOperations.length; i++) { // && KillDraw < tilesDrawn
+ var Msg = obj.PendingOperations[i];
+ if (Msg[0] == (obj.TilesDrawn + 1)) {
+ if (Msg[1] == 1) { obj.ProcessCopyRectMsg(Msg[2]); }
+ else if (Msg[1] == 2) { obj.Canvas.drawImage(Msg[2], obj.rotX(Msg[3], Msg[4]), obj.rotY(Msg[3], Msg[4])); delete Msg[2]; }
+ obj.PendingOperations.splice(i, 1);
+ delete Msg;
+ obj.TilesDrawn++;
+ if (obj.TilesDrawn == obj.tilesReceived && obj.KillDraw < obj.TilesDrawn) { obj.KillDraw = obj.TilesDrawn = obj.tilesReceived = 0; }
+ return true;
+ }
+ }
+ if (obj.oldie && obj.PendingOperations.length > 0) { obj.TilesDrawn++; }
+ return false;
+ }
+
+ obj.ProcessCopyRectMsg = function (str) {
+ var SX = ((str.charCodeAt(0) & 0xFF) << 8) + (str.charCodeAt(1) & 0xFF);
+ var SY = ((str.charCodeAt(2) & 0xFF) << 8) + (str.charCodeAt(3) & 0xFF);
+ var DX = ((str.charCodeAt(4) & 0xFF) << 8) + (str.charCodeAt(5) & 0xFF);
+ var DY = ((str.charCodeAt(6) & 0xFF) << 8) + (str.charCodeAt(7) & 0xFF);
+ var WIDTH = ((str.charCodeAt(8) & 0xFF) << 8) + (str.charCodeAt(9) & 0xFF);
+ var HEIGHT = ((str.charCodeAt(10) & 0xFF) << 8) + (str.charCodeAt(11) & 0xFF);
+ obj.Canvas.drawImage(Canvas.canvas, SX, SY, WIDTH, HEIGHT, DX, DY, WIDTH, HEIGHT);
+ }
+
+ obj.SendUnPause = function () {
+ //obj.Debug("SendUnPause");
+ //obj.xxStateChange(3);
+ obj.send(String.fromCharCode(0x00, 0x08, 0x00, 0x05, 0x00));
+ }
+
+ obj.SendPause = function () {
+ //obj.Debug("SendPause");
+ //obj.xxStateChange(2);
+ obj.send(String.fromCharCode(0x00, 0x08, 0x00, 0x05, 0x01));
+ }
+
+ obj.SendCompressionLevel = function (type, level, scaling, frametimer) {
+ if (level) { obj.CompressionLevel = level; }
+ if (scaling) { obj.ScalingLevel = scaling; }
+ if (frametimer) { obj.FrameRateTimer = frametimer; }
+ obj.send(String.fromCharCode(0x00, 0x05, 0x00, 0x0A, type, obj.CompressionLevel) + obj.shortToStr(obj.ScalingLevel) + obj.shortToStr(obj.FrameRateTimer));
+ }
+
+ obj.SendRefresh = function () {
+ obj.send(String.fromCharCode(0x00, 0x06, 0x00, 0x04));
+ }
+
+ obj.ProcessScreenMsg = function (width, height) {
+ if (obj.debugmode > 0) { console.log("ScreenSize: " + width + " x " + height); }
+ obj.Canvas.setTransform(1, 0, 0, 1, 0, 0);
+ obj.rotation = 0;
+ obj.FirstDraw = true;
+ obj.ScreenWidth = obj.width = width;
+ obj.ScreenHeight = obj.height = height;
+ obj.KillDraw = obj.tilesReceived;
+ while (obj.PendingOperations.length > 0) { obj.PendingOperations.shift(); }
+ obj.SendCompressionLevel(1);
+ obj.SendUnPause();
+ if (obj.onScreenSizeChange != null) { obj.onScreenSizeChange(obj, obj.ScreenWidth, obj.ScreenHeight, obj.CanvasId); }
+ }
+
+ obj.ProcessData = function (str) {
+ var ptr = 0;
+ //console.log('x0', str.length);
+ while (ptr < str.length) {
+ //console.log('x1', ptr, str.length);
+ ptr += obj.ProcessDataEx(str.substring(ptr));
+ //console.log('x2', ptr, str.length);
+ }
+ }
+
+ obj.ProcessDataEx = function (str) {
+ if (obj.accumulator != null) {
+ str = obj.accumulator + str;
+ //console.log('KVM using accumulated data, total size is now ' + str.length + ' bytes.');
+ obj.accumulator = null;
+ }
+ if (obj.debugmode > 1) { console.log("KRecv(" + str.length + "): " + rstr2hex(str.substring(0, Math.min(str.length, 40)))); }
+ if (str.length < 4) return;
+ var cmdmsg = null, X = 0, Y = 0, command = ReadShort(str, 0), cmdsize = ReadShort(str, 2), jumboAdd = 0;
+ if ((command == 27) && (cmdsize == 8)) {
+ // Jumbo packet
+ if (str.length < 12) return;
+ command = ReadShort(str, 8)
+ cmdsize = ReadInt(str, 4);
+ //console.log('JUMBO cmd=' + command + ', cmdsize=' + cmdsize + ', data received=' + str.length);
+ if ((cmdsize + 8) > str.length) {
+ //console.log('KVM accumulator set to ' + str.length + ' bytes, need ' + cmdsize + ' bytes.');
+ obj.accumulator = str;
+ return;
+ }
+ str = str.substring(8);
+ jumboAdd = 8;
+ }
+ if ((cmdsize != str.length) && (obj.debugmode > 0)) { console.log(cmdsize, str.length, cmdsize == str.length); }
+ if ((command >= 18) && (command != 65)) { console.error("Invalid KVM command " + command + " of size " + cmdsize); console.log("Invalid KVM data", str.length, rstr2hex(str.substring(0, 40)) + '...'); return; }
+ if (cmdsize > str.length) {
+ //console.log('KVM accumulator set to ' + str.length + ' bytes, need ' + cmdsize + ' bytes.');
+ obj.accumulator = str;
+ return;
+ }
+ //console.log("KVM Command: " + command + " Len:" + cmdsize);
+
+ if (command == 3 || command == 4 || command == 7) {
+ cmdmsg = str.substring(4, cmdsize);
+ X = ((cmdmsg.charCodeAt(0) & 0xFF) << 8) + (cmdmsg.charCodeAt(1) & 0xFF);
+ Y = ((cmdmsg.charCodeAt(2) & 0xFF) << 8) + (cmdmsg.charCodeAt(3) & 0xFF);
+ if (obj.debugmode > 0) { console.log("CMD" + command + " at X=" + X + " Y=" + Y); }
+ }
+
+ switch (command) {
+ case 3: // Tile
+ if (obj.FirstDraw) obj.onResize();
+ obj.ProcessPictureMsg(cmdmsg, X, Y);
+ break;
+ case 4: // Tile Copy
+ if (obj.FirstDraw) obj.onResize();
+ if (obj.TilesDrawn == obj.tilesReceived) {
+ obj.ProcessCopyRectMsg(cmdmsg);
+ } else {
+ obj.PendingOperations.push([ ++tilesReceived, 1, cmdmsg ]);
+ }
+ break;
+ case 7: // Screen size
+ obj.ProcessScreenMsg(X, Y);
+ obj.SendKeyMsgKC(obj.KeyAction.UP, 16); // Shift
+ obj.SendKeyMsgKC(obj.KeyAction.UP, 17); // Ctrl
+ obj.SendKeyMsgKC(obj.KeyAction.UP, 18); // Alt
+ obj.SendKeyMsgKC(obj.KeyAction.UP, 91); // Left-Windows
+ obj.SendKeyMsgKC(obj.KeyAction.UP, 92); // Right-Windows
+ obj.SendKeyMsgKC(obj.KeyAction.UP, 16); // Shift
+ obj.send(String.fromCharCode(0x00, 0x0E, 0x00, 0x04));
+ break;
+ case 11: // GetDisplays
+ var selectedDisplay = 0, displays = { }, dcount = ((str.charCodeAt(4) & 0xFF) << 8) + (str.charCodeAt(5) & 0xFF);
+ if (dcount > 0) {
+ // Many displays present
+ selectedDisplay = ((str.charCodeAt(6 + (dcount * 2)) & 0xFF) << 8) + (str.charCodeAt(7 + (dcount * 2)) & 0xFF);
+ for (var i = 0; i < dcount; i++) {
+ var disp = ((str.charCodeAt(6 + (i * 2)) & 0xFF) << 8) + (str.charCodeAt(7 + (i * 2)) & 0xFF);
+ if (disp == 65535) { displays[disp] = 'All Displays'; } else { displays[disp] = 'Display ' + disp; }
+ }
+ }
+ //console.log('Get Displays', displays, selectedDisplay, rstr2hex(str));
+ if (obj.onDisplayinfo != null) { obj.onDisplayinfo(obj, displays, selectedDisplay); }
+ break;
+ case 12: // SetDisplay
+ //console.log('SetDisplayConfirmed');
+ break;
+ case 14: // KVM_INIT_TOUCH
+ obj.touchenabled = 1;
+ obj.TouchArray = {};
+ if (obj.onTouchEnabledChanged != null) obj.onTouchEnabledChanged(obj.touchenabled);
+ break;
+ case 15: // KVM_TOUCH
+ obj.TouchArray = {};
+ break;
+ case 16: // MNG_KVM_CONNECTCOUNT
+ obj.connectioncount = ReadInt(str, 4);
+ //obj.Debug("Got KVM Connect Count: " + obj.connectioncount);
+ if (obj.onConnectCountChanged != null) obj.onConnectCountChanged(obj.connectioncount, obj);
+ break;
+ case 17: // MNG_KVM_MESSAGE
+ //obj.Debug("Got KVM Message: " + str.substring(4, cmdsize));
+ if (obj.onMessage != null) obj.onMessage(str.substring(4, cmdsize), obj);
+ break;
+ case 65: // Alert
+ str = str.substring(4);
+ if (str[0] != '.') {
+ console.log(str); //alert('KVM: ' + str);
+ if (obj.parent != null) {
+ obj.parent.consoleMessage = str;
+ if (obj.parent.onConsoleMessageChange) { obj.parent.onConsoleMessageChange(obj.parent, str); }
+ }
+ } else {
+ console.log('KVM: ' + str.substring(1));
+ }
+ break;
+ }
+ return cmdsize + jumboAdd;
+ }
+
+ // Keyboard and Mouse I/O.
+ obj.MouseButton = { "NONE": 0x00, "LEFT": 0x02, "RIGHT": 0x08, "MIDDLE": 0x20 };
+ obj.KeyAction = { "NONE": 0, "DOWN": 1, "UP": 2, "SCROLL": 3, "EXUP": 4, "EXDOWN": 5, "DBLCLICK": 6 };
+ obj.InputType = { "KEY": 1, "MOUSE": 2, "CTRLALTDEL": 10, "TOUCH": 15 };
+ obj.Alternate = 0;
+
+ var convertKeyCodeTable = {
+ "Pause": 19,
+ "CapsLock": 20,
+ "Space": 32,
+ "Quote": 222,
+ "Minus": 189,
+ "NumpadMultiply": 106,
+ "NumpadAdd": 107,
+ "PrintScreen": 44,
+ "Comma": 188,
+ "NumpadSubtract": 109,
+ "NumpadDecimal": 110,
+ "Period": 190,
+ "Slash": 191,
+ "NumpadDivide": 111,
+ "Semicolon": 186,
+ "Equal": 187,
+ "OSLeft": 91,
+ "BracketLeft": 219,
+ "OSRight": 91,
+ "Backslash": 220,
+ "BracketRight": 221,
+ "ContextMenu": 93,
+ "Backquote": 192,
+ "NumLock": 144,
+ "ScrollLock": 145,
+ "Backspace": 8,
+ "Tab": 9,
+ "Enter": 13,
+ "NumpadEnter": 13,
+ "Escape": 27,
+ "Delete": 46,
+ "Home": 36,
+ "PageUp": 33,
+ "PageDown": 34,
+ "ArrowLeft": 37,
+ "ArrowUp": 38,
+ "ArrowRight": 39,
+ "ArrowDown": 40,
+ "End": 35,
+ "Insert": 45,
+ "F1": 112,
+ "F2": 113,
+ "F3": 114,
+ "F4": 115,
+ "F5": 116,
+ "F6": 117,
+ "F7": 118,
+ "F8": 119,
+ "F9": 120,
+ "F10": 121,
+ "F11": 122,
+ "F12": 123,
+ "ShiftLeft": 16,
+ "ShiftRight": 16,
+ "ControlLeft": 17,
+ "ControlRight": 17,
+ "AltLeft": 18,
+ "AltRight": 18,
+ "MetaLeft": 91,
+ "MetaRight": 92,
+ "VolumeMute": 181
+ //"LaunchMail":
+ //"LaunchApp1":
+ //"LaunchApp2":
+ //"BrowserStop":
+ //"MediaStop":
+ //"MediaTrackPrevious":
+ //"MediaTrackNext":
+ //"MediaPlayPause":
+ //"MediaSelect":
+ }
+
+ function convertKeyCode(e) {
+ if (e.code.startsWith('Key') && e.code.length == 4) { return e.code.charCodeAt(3); }
+ if (e.code.startsWith('Digit') && e.code.length == 6) { return e.code.charCodeAt(5); }
+ if (e.code.startsWith('Numpad') && e.code.length == 7) { return e.code.charCodeAt(6) + 48; }
+ return convertKeyCodeTable[e.code];
+ }
+
+ obj.SendKeyMsg = function (action, event) {
+ if (action == null) return;
+ if (!event) { event = window.event; }
+ if (event.code && (obj.localKeyMap == false)) {
+ // Convert "event.code" into a scancode. This works the same regardless of the keyboard language.
+ // Older browsers will not support this.
+ var kc = convertKeyCode(event);
+ if (kc != null) { obj.SendKeyMsgKC(action, kc); }
+ } else {
+ // Use this keycode, this works best with "US-EN" keyboards.
+ // Older browser support this.
+ var kc = event.keyCode;
+ if (kc == 0x3B) { kc = 0xBA; } // Fix the ';' key
+ else if (kc == 173) { kc = 189; } // Fix the '-' key for Firefox
+ else if (kc == 61) { kc = 187; } // Fix the '=' key for Firefox
+ obj.SendKeyMsgKC(action, kc);
+ }
+ }
+
+ obj.SendMessage = function (msg) {
+ if (obj.State == 3) obj.send(String.fromCharCode(0x00, 0x11) + obj.shortToStr(4 + msg.length) + msg); // 0x11 = 17 MNG_KVM_MESSAGE
+ }
+
+ obj.SendKeyMsgKC = function (action, kc) {
+ //console.log('SendKeyMsgKC', action, kc);
+ if (obj.State != 3) return;
+ if (typeof action == 'object') { for (var i in action) { obj.SendKeyMsgKC(action[i][0], action[i][1]); } }
+ else { obj.send(String.fromCharCode(0x00, obj.InputType.KEY, 0x00, 0x06, (action - 1), kc)); }
+ }
+
+ obj.sendcad = function() { obj.SendCtrlAltDelMsg(); }
+
+ obj.SendCtrlAltDelMsg = function () {
+ if (obj.State == 3) { obj.send(String.fromCharCode(0x00, obj.InputType.CTRLALTDEL, 0x00, 0x04)); }
+ }
+
+ obj.SendEscKey = function () {
+ if (obj.State == 3) obj.send(String.fromCharCode(0x00, obj.InputType.KEY, 0x00, 0x06, 0x00, 0x1B, 0x00, obj.InputType.KEY, 0x00, 0x06, 0x01, 0x1B));
+ }
+
+ obj.SendStartMsg = function () {
+ obj.SendKeyMsgKC(obj.KeyAction.EXDOWN, 0x5B); // L-Windows
+ obj.SendKeyMsgKC(obj.KeyAction.EXUP, 0x5B); // L-Windows
+ }
+
+ obj.SendCharmsMsg = function () {
+ obj.SendKeyMsgKC(obj.KeyAction.EXDOWN, 0x5B); // L-Windows
+ obj.SendKeyMsgKC(obj.KeyAction.DOWN, 67); // C
+ obj.SendKeyMsgKC(obj.KeyAction.UP, 67); // C
+ obj.SendKeyMsgKC(obj.KeyAction.EXUP, 0x5B); // L-Windows
+ }
+
+ obj.SendTouchMsg1 = function (id, flags, x, y) {
+ if (obj.State == 3) obj.send(String.fromCharCode(0x00, obj.InputType.TOUCH) + obj.shortToStr(14) + String.fromCharCode(0x01, id) + obj.intToStr(flags) + obj.shortToStr(x) + obj.shortToStr(y));
+ }
+
+ obj.SendTouchMsg2 = function (id, flags) {
+ var msg = '';
+ var flags2;
+ var str = "TOUCHSEND: ";
+ for (var k in obj.TouchArray) {
+ if (k == id) { flags2 = flags; } else {
+ if (obj.TouchArray[k].f == 1) { flags2 = 0x00010000 | 0x00000002 | 0x00000004; obj.TouchArray[k].f = 3; str += "START" + k; } // POINTER_FLAG_DOWN
+ else if (obj.TouchArray[k].f == 2) { flags2 = 0x00040000; str += "STOP" + k; } // POINTER_FLAG_UP
+ else flags2 = 0x00000002 | 0x00000004 | 0x00020000; // POINTER_FLAG_UPDATE
+ }
+ msg += String.fromCharCode(k) + obj.intToStr(flags2) + obj.shortToStr(obj.TouchArray[k].x) + obj.shortToStr(obj.TouchArray[k].y);
+ if (obj.TouchArray[k].f == 2) delete obj.TouchArray[k];
+ }
+ if (obj.State == 3) obj.send(String.fromCharCode(0x00, obj.InputType.TOUCH) + obj.shortToStr(5 + msg.length) + String.fromCharCode(0x02) + msg);
+ if (Object.keys(obj.TouchArray).length == 0 && obj.touchtimer != null) { clearInterval(obj.touchtimer); obj.touchtimer = null; }
+ }
+
+ obj.SendMouseMsg = function (Action, event) {
+ if (obj.State != 3) return;
+ if (Action != null && obj.Canvas != null) {
+ if (!event) { var event = window.event; }
+
+ var ScaleFactorHeight = (obj.Canvas.canvas.height / obj.CanvasId.clientHeight);
+ var ScaleFactorWidth = (obj.Canvas.canvas.width / obj.CanvasId.clientWidth);
+ var Offsets = obj.GetPositionOfControl(obj.Canvas.canvas);
+ var X = ((event.pageX - Offsets[0]) * ScaleFactorWidth);
+ var Y = ((event.pageY - Offsets[1]) * ScaleFactorHeight);
+ if (event.addx) { X += event.addx; }
+ if (event.addy) { Y += event.addy; }
+
+ if (X >= 0 && X <= obj.Canvas.canvas.width && Y >= 0 && Y <= obj.Canvas.canvas.height) {
+ var Button = 0;
+ var Delta = 0;
+ if (Action == obj.KeyAction.UP || Action == obj.KeyAction.DOWN) {
+ if (event.which) { ((event.which == 1) ? (Button = obj.MouseButton.LEFT) : ((event.which == 2) ? (Button = obj.MouseButton.MIDDLE) : (Button = obj.MouseButton.RIGHT))); }
+ else if (event.button) { ((event.button == 0) ? (Button = obj.MouseButton.LEFT) : ((event.button == 1) ? (Button = obj.MouseButton.MIDDLE) : (Button = obj.MouseButton.RIGHT))); }
+ }
+ else if (Action == obj.KeyAction.SCROLL) {
+ if (event.detail) { Delta = (-1 * (event.detail * 120)); } else if (event.wheelDelta) { Delta = (event.wheelDelta * 3); }
+ }
+
+ var MouseMsg = "";
+ if (Action == obj.KeyAction.DBLCLICK) {
+ MouseMsg = String.fromCharCode(0x00, obj.InputType.MOUSE, 0x00, 0x0A, 0x00, 0x88, ((X / 256) & 0xFF), (X & 0xFF), ((Y / 256) & 0xFF), (Y & 0xFF));
+ } else if (Action == obj.KeyAction.SCROLL) {
+ MouseMsg = String.fromCharCode(0x00, obj.InputType.MOUSE, 0x00, 0x0C, 0x00, 0x00, ((X / 256) & 0xFF), (X & 0xFF), ((Y / 256) & 0xFF), (Y & 0xFF), ((Delta / 256) & 0xFF), (Delta & 0xFF));
+ } else {
+ MouseMsg = String.fromCharCode(0x00, obj.InputType.MOUSE, 0x00, 0x0A, 0x00, ((Action == obj.KeyAction.DOWN) ? Button : ((Button * 2) & 0xFF)), ((X / 256) & 0xFF), (X & 0xFF), ((Y / 256) & 0xFF), (Y & 0xFF));
+ }
+
+ if (obj.Action == obj.KeyAction.NONE) {
+ if (obj.Alternate == 0 || obj.ipad) { obj.send(MouseMsg); obj.Alternate = 1; } else { obj.Alternate = 0; }
+ } else {
+ obj.send(MouseMsg);
+ }
+ }
+ }
+ }
+
+ obj.GetDisplayNumbers = function () { obj.send(String.fromCharCode(0x00, 0x0B, 0x00, 0x04)); } // Get Terminal display
+ obj.SetDisplay = function (number) { console.log('Set display', number); obj.send(String.fromCharCode(0x00, 0x0C, 0x00, 0x06, number >> 8, number & 0xFF)); } // Set Terminal display
+ obj.intToStr = function (x) { return String.fromCharCode((x >> 24) & 0xFF, (x >> 16) & 0xFF, (x >> 8) & 0xFF, x & 0xFF); }
+ obj.shortToStr = function (x) { return String.fromCharCode((x >> 8) & 0xFF, x & 0xFF); }
+
+ obj.onResize = function () {
+ if (obj.ScreenWidth == 0 || obj.ScreenHeight == 0) return;
+ if (obj.Canvas.canvas.width == obj.ScreenWidth && obj.Canvas.canvas.height == obj.ScreenHeight) return;
+ if (obj.FirstDraw) {
+ obj.Canvas.canvas.width = obj.ScreenWidth;
+ obj.Canvas.canvas.height = obj.ScreenHeight;
+ obj.Canvas.fillRect(0, 0, obj.ScreenWidth, obj.ScreenHeight);
+ if (obj.onScreenSizeChange != null) obj.onScreenSizeChange(obj, obj.ScreenWidth, obj.ScreenHeight, obj.CanvasId);
+ }
+ obj.FirstDraw = false;
+ //obj.Debug("onResize: " + obj.ScreenWidth + " x " + obj.ScreenHeight);
+ }
+
+ obj.xxMouseInputGrab = false;
+ obj.xxKeyInputGrab = false;
+ obj.xxMouseMove = function (e) { if (obj.State == 3) obj.SendMouseMsg(obj.KeyAction.NONE, e); if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
+ obj.xxMouseUp = function (e) { if (obj.State == 3) obj.SendMouseMsg(obj.KeyAction.UP, e); if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
+ obj.xxMouseDown = function (e) { if (obj.State == 3) obj.SendMouseMsg(obj.KeyAction.DOWN, e); if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
+ obj.xxMouseDblClick = function (e) { if (obj.State == 3) obj.SendMouseMsg(obj.KeyAction.DBLCLICK, e); if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
+ obj.xxDOMMouseScroll = function (e) { if (obj.State == 3) { obj.SendMouseMsg(obj.KeyAction.SCROLL, e); return false; } return true; }
+ obj.xxMouseWheel = function (e) { if (obj.State == 3) { obj.SendMouseMsg(obj.KeyAction.SCROLL, e); return false; } return true; }
+ obj.xxKeyUp = function (e) { if (obj.State == 3) { obj.SendKeyMsg(obj.KeyAction.UP, e); } if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
+ obj.xxKeyDown = function (e) { if (obj.State == 3) { obj.SendKeyMsg(obj.KeyAction.DOWN, e); } if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
+ obj.xxKeyPress = function (e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
+
+ // Key handlers
+ obj.handleKeys = function (e) { if (obj.stopInput == true || desktop.State != 3) return false; return obj.xxKeyPress(e); }
+ obj.handleKeyUp = function (e) {
+ if (obj.stopInput == true || desktop.State != 3) return false;
+ if (obj.firstUpKeys.length < 5) {
+ obj.firstUpKeys.push(e.keyCode);
+ if ((obj.firstUpKeys.length == 5)) { var j = obj.firstUpKeys.join(','); if ((j == '16,17,91,91,16') || (j == '16,17,18,91,92')) { obj.stopInput = true; } }
+ }
+ if (e.keyCode == 16) { obj.shiftPressed = false; }
+ if (e.keyCode == 17) { obj.ctrlPressed = false; }
+ if (e.keyCode == 18) { obj.altPressed = false; }
+ return obj.xxKeyUp(e);
+ }
+ obj.handleKeyDown = function (e) {
+ if (obj.stopInput == true || desktop.State != 3) return false;
+ if (e.keyCode == 16) { obj.shiftPressed = true; }
+ if (e.keyCode == 17) { obj.ctrlPressed = true; }
+ if (e.keyCode == 18) { obj.altPressed = true; }
+ return obj.xxKeyDown(e);
+ }
+
+ // Release the CTRL, ALT, SHIFT keys if they are pressed.
+ obj.handleReleaseKeys = function () {
+ if (obj.shiftPressed) { obj.SendKeyMsgKC(obj.KeyAction.UP, 16); } // Shift
+ if (obj.ctrlPressed) { obj.SendKeyMsgKC(obj.KeyAction.UP, 17); } // Ctrl
+ if (obj.altPressed) { obj.SendKeyMsgKC(obj.KeyAction.UP, 18); } // Alt
+ obj.shiftPressed = obj.ctrlPressed = obj.altPressed = false;
+ }
+
+ // Mouse handlers
+ obj.mousedblclick = function (e) { if (obj.stopInput == true) return false; return obj.xxMouseDblClick(e); }
+ obj.mousedown = function (e) { if (obj.stopInput == true) return false; return obj.xxMouseDown(e); }
+ obj.mouseup = function (e) { if (obj.stopInput == true) return false; return obj.xxMouseUp(e); }
+ obj.mousemove = function (e) { if (obj.stopInput == true) return false; return obj.xxMouseMove(e); }
+ obj.mousewheel = function (e) { if (obj.stopInput == true) return false; return obj.xxMouseWheel(e); }
+
+ obj.xxMsTouchEvent = function (evt) {
+ if (evt.originalEvent.pointerType == 4) return; // If this is a mouse pointer, ignore this event. Touch & pen are ok.
+ if (evt.preventDefault) evt.preventDefault();
+ if (evt.stopPropagation) evt.stopPropagation();
+ if (evt.type == 'MSPointerDown' || evt.type == 'MSPointerMove' || evt.type == 'MSPointerUp') {
+ var flags = 0;
+ var id = evt.originalEvent.pointerId % 256;
+ var X = evt.offsetX * (Canvas.canvas.width / obj.CanvasId.clientWidth);
+ var Y = evt.offsetY * (Canvas.canvas.height / obj.CanvasId.clientHeight);
+
+ if (evt.type == 'MSPointerDown') flags = 0x00010000 | 0x00000002 | 0x00000004; // POINTER_FLAG_DOWN
+ else if (evt.type == 'MSPointerMove') {
+ //if (obj.TouchArray[id] && MuchTheSame(obj.TouchArray[id].x, X) && MuchTheSame(obj.TouchArray[id].y, Y)) return;
+ flags = 0x00020000 | 0x00000002 | 0x00000004; // POINTER_FLAG_UPDATE
+ }
+ else if (evt.type == 'MSPointerUp') flags = 0x00040000; // POINTER_FLAG_UP
+
+ if (!obj.TouchArray[id]) obj.TouchArray[id] = { x: X, y : Y };
+ obj.SendTouchMsg2(id, flags)
+ if (evt.type == 'MSPointerUp') delete obj.TouchArray[id];
+ } else {
+ alert(evt.type);
+ }
+ return true;
+ }
+
+ obj.xxTouchStart = function (e) {
+ if (obj.State != 3) return;
+ if (e.preventDefault) e.preventDefault();
+ if (obj.touchenabled == 0 || obj.touchenabled == 1) {
+ if (e.originalEvent.touches.length > 1) return;
+ var t = e.originalEvent.touches[0];
+ e.which = 1;
+ obj.LastX = e.pageX = t.pageX;
+ obj.LastY = e.pageY = t.pageY;
+ obj.SendMouseMsg(KeyAction.DOWN, e);
+ } else {
+ var Offsets = obj.GetPositionOfControl(Canvas.canvas);
+ for (var i in e.originalEvent.changedTouches) {
+ if (!e.originalEvent.changedTouches[i].identifier) continue;
+ var id = e.originalEvent.changedTouches[i].identifier % 256;
+ if (!obj.TouchArray[id]) { obj.TouchArray[id] = { x: (e.originalEvent.touches[i].pageX - Offsets[0]) * (Canvas.canvas.width / obj.CanvasId.clientWidth), y: (e.originalEvent.touches[i].pageY - Offsets[1]) * (Canvas.canvas.height / obj.CanvasId.clientHeight), f: 1 }; }
+ }
+ if (Object.keys(obj.TouchArray).length > 0 && touchtimer == null) { obj.touchtimer = setInterval(function () { obj.SendTouchMsg2(256, 0); }, 50); }
+ }
+ }
+
+ obj.xxTouchMove = function (e) {
+ if (obj.State != 3) return;
+ if (e.preventDefault) e.preventDefault();
+ if (obj.touchenabled == 0 || obj.touchenabled == 1) {
+ if (e.originalEvent.touches.length > 1) return;
+ var t = e.originalEvent.touches[0];
+ e.which = 1;
+ obj.LastX = e.pageX = t.pageX;
+ obj.LastY = e.pageY = t.pageY;
+ obj.SendMouseMsg(obj.KeyAction.NONE, e);
+ } else {
+ var Offsets = obj.GetPositionOfControl(Canvas.canvas);
+ for (var i in e.originalEvent.changedTouches) {
+ if (!e.originalEvent.changedTouches[i].identifier) continue;
+ var id = e.originalEvent.changedTouches[i].identifier % 256;
+ if (obj.TouchArray[id]) {
+ obj.TouchArray[id].x = (e.originalEvent.touches[i].pageX - Offsets[0]) * (obj.Canvas.canvas.width / obj.CanvasId.clientWidth);
+ obj.TouchArray[id].y = (e.originalEvent.touches[i].pageY - Offsets[1]) * (obj.Canvas.canvas.height / obj.CanvasId.clientHeight);
+ }
+ }
+ }
+ }
+
+ obj.xxTouchEnd = function (e) {
+ if (obj.State != 3) return;
+ if (e.preventDefault) e.preventDefault();
+ if (obj.touchenabled == 0 || obj.touchenabled == 1) {
+ if (e.originalEvent.touches.length > 1) return;
+ e.which = 1;
+ e.pageX = LastX;
+ e.pageY = LastY;
+ obj.SendMouseMsg(KeyAction.UP, e);
+ } else {
+ for (var i in e.originalEvent.changedTouches) {
+ if (!e.originalEvent.changedTouches[i].identifier) continue;
+ var id = e.originalEvent.changedTouches[i].identifier % 256;
+ if (obj.TouchArray[id]) obj.TouchArray[id].f = 2;
+ }
+ }
+ }
+
+ obj.GrabMouseInput = function () {
+ if (obj.xxMouseInputGrab == true) return;
+ var c = obj.CanvasId;
+ c.onmousemove = obj.xxMouseMove;
+ c.onmouseup = obj.xxMouseUp;
+ c.onmousedown = obj.xxMouseDown;
+ c.touchstart = obj.xxTouchStart;
+ c.touchmove = obj.xxTouchMove;
+ c.touchend = obj.xxTouchEnd;
+ c.MSPointerDown = obj.xxMsTouchEvent;
+ c.MSPointerMove = obj.xxMsTouchEvent;
+ c.MSPointerUp = obj.xxMsTouchEvent;
+ if (navigator.userAgent.match(/mozilla/i)) c.DOMMouseScroll = obj.xxDOMMouseScroll; else c.onmousewheel = obj.xxMouseWheel;
+ obj.xxMouseInputGrab = true;
+ }
+
+ obj.UnGrabMouseInput = function () {
+ if (obj.xxMouseInputGrab == false) return;
+ var c = obj.CanvasId;
+ c.onmousemove = null;
+ c.onmouseup = null;
+ c.onmousedown = null;
+ c.touchstart = null;
+ c.touchmove = null;
+ c.touchend = null;
+ c.MSPointerDown = null;
+ c.MSPointerMove = null;
+ c.MSPointerUp = null;
+ if (navigator.userAgent.match(/mozilla/i)) c.DOMMouseScroll = null; else c.onmousewheel = null;
+ obj.xxMouseInputGrab = false;
+ }
+
+ obj.GrabKeyInput = function () {
+ if (obj.xxKeyInputGrab == true) return;
+ document.onkeyup = obj.xxKeyUp;
+ document.onkeydown = obj.xxKeyDown;
+ document.onkeypress = obj.xxKeyPress;
+ obj.xxKeyInputGrab = true;
+ }
+
+ obj.UnGrabKeyInput = function () {
+ if (obj.xxKeyInputGrab == false) return;
+ document.onkeyup = null;
+ document.onkeydown = null;
+ document.onkeypress = null;
+ obj.xxKeyInputGrab = false;
+ }
+
+ obj.GetPositionOfControl = function (Control) {
+ var Position = Array(2);
+ Position[0] = Position[1] = 0;
+ while (Control) { Position[0] += Control.offsetLeft; Position[1] += Control.offsetTop; Control = Control.offsetParent; }
+ return Position;
+ }
+
+ obj.crotX = function (x, y) {
+ if (obj.rotation == 0) return x;
+ if (obj.rotation == 1) return y;
+ if (obj.rotation == 2) return obj.Canvas.canvas.width - x;
+ if (obj.rotation == 3) return obj.Canvas.canvas.height - y;
+ }
+
+ obj.crotY = function (x, y) {
+ if (obj.rotation == 0) return y;
+ if (obj.rotation == 1) return obj.Canvas.canvas.width - x;
+ if (obj.rotation == 2) return obj.Canvas.canvas.height - y;
+ if (obj.rotation == 3) return x;
+ }
+
+ obj.rotX = function (x, y) {
+ if (obj.rotation == 0 || obj.rotation == 1) return x;
+ if (obj.rotation == 2) return x - obj.Canvas.canvas.width;
+ if (obj.rotation == 3) return x - obj.Canvas.canvas.height;
+ }
+
+ obj.rotY = function (x, y) {
+ if (obj.rotation == 0 || obj.rotation == 3) return y;
+ if (obj.rotation == 1) return y - obj.Canvas.canvas.width;
+ if (obj.rotation == 2) return y - obj.Canvas.canvas.height;
+ }
+
+ obj.tcanvas = null;
+ obj.setRotation = function (x) {
+ while (x < 0) { x += 4; }
+ var newrotation = x % 4;
+ if (newrotation == obj.rotation) return true;
+ var rw = obj.Canvas.canvas.width;
+ var rh = obj.Canvas.canvas.height;
+ if (obj.rotation == 1 || obj.rotation == 3) { rw = obj.Canvas.canvas.height; rh = obj.Canvas.canvas.width; }
+
+ // Copy the canvas, put it back in the correct direction
+ if (obj.tcanvas == null) obj.tcanvas = document.createElement('canvas');
+ var tcanvasctx = obj.tcanvas.getContext('2d');
+ tcanvasctx.setTransform(1, 0, 0, 1, 0, 0);
+ tcanvasctx.canvas.width = rw;
+ tcanvasctx.canvas.height = rh;
+ tcanvasctx.rotate((obj.rotation * -90) * Math.PI / 180);
+ if (obj.rotation == 0) tcanvasctx.drawImage(obj.Canvas.canvas, 0, 0);
+ if (obj.rotation == 1) tcanvasctx.drawImage(obj.Canvas.canvas, -obj.Canvas.canvas.width, 0);
+ if (obj.rotation == 2) tcanvasctx.drawImage(obj.Canvas.canvas, -obj.Canvas.canvas.width, -obj.Canvas.canvas.height);
+ if (obj.rotation == 3) tcanvasctx.drawImage(obj.Canvas.canvas, 0, -obj.Canvas.canvas.height);
+
+ // Change the size and orientation and copy the canvas back into the rotation
+ if (obj.rotation == 0 || obj.rotation == 2) { obj.Canvas.canvas.height = rw; obj.Canvas.canvas.width = rh; }
+ if (obj.rotation == 1 || obj.rotation == 3) { obj.Canvas.canvas.height = rh; obj.Canvas.canvas.width = rw; }
+ obj.Canvas.setTransform(1, 0, 0, 1, 0, 0);
+ obj.Canvas.rotate((newrotation * 90) * Math.PI / 180);
+ obj.rotation = newrotation;
+ obj.Canvas.drawImage(obj.tcanvas, obj.rotX(0, 0), obj.rotY(0, 0));
+
+ obj.ScreenWidth = obj.Canvas.canvas.width;
+ obj.ScreenHeight = obj.Canvas.canvas.height;
+ if (obj.onScreenSizeChange != null) obj.onScreenSizeChange(obj, obj.ScreenWidth, obj.ScreenHeight, obj.CanvasId);
+ return true;
+ }
+
+ // Private method
+ obj.MuchTheSame = function (a, b) { return (Math.abs(a - b) < 4); }
+ obj.Debug = function (msg) { console.log(msg); }
+ obj.getIEVersion = function () { var r = -1; if (navigator.appName == 'Microsoft Internet Explorer') { var ua = navigator.userAgent; var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})"); if (re.exec(ua) != null) r = parseFloat(RegExp.$1); } return r; }
+ obj.haltEvent = function (e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
+
+ return obj;
+}
diff --git a/agent-redir-rtc-0.1.0.js b/agent-redir-rtc-0.1.0.js
new file mode 100644
index 0000000..fd60b27
--- /dev/null
+++ b/agent-redir-rtc-0.1.0.js
@@ -0,0 +1,145 @@
+/**
+* @description Mesh Agent Transport Module - using websocket relay
+* @author Ylian Saint-Hilaire
+* @version v0.0.1
+*/
+
+// Construct a MeshServer agent direction object
+var CreateKvmDataChannel = function (webchannel, module, keepalive) {
+ var obj = {};
+ obj.m = module; // This is the inner module (Terminal or Desktop)
+ module.parent = obj;
+ obj.webchannel = webchannel;
+ obj.State = 0;
+ obj.protocol = module.protocol; // 1 = SOL, 2 = KVM, 3 = IDER, 4 = Files, 5 = FileTransfer
+ obj.onStateChanged = null;
+ obj.onControlMsg = null;
+ obj.debugmode = 0;
+ obj.keepalive = keepalive;
+ obj.rtcKeepAlive = null;
+
+ // Private method
+ //obj.debug = function (msg) { console.log(msg); }
+
+ obj.Start = function () {
+ if (obj.debugmode == 1) { console.log('start'); }
+ obj.xxStateChange(3);
+ obj.webchannel.onmessage = obj.xxOnMessage;
+ obj.rtcKeepAlive = setInterval(obj.xxSendRtcKeepAlive, 30000);
+ }
+
+ // Setup the file reader
+ var fileReader = new FileReader();
+ var fileReaderInuse = false, fileReaderAcc = [];
+ if (fileReader.readAsBinaryString) {
+ // Chrome & Firefox (Draft)
+ fileReader.onload = function (e) { obj.xxOnSocketData(e.target.result); if (fileReaderAcc.length == 0) { fileReaderInuse = false; } else { fileReader.readAsBinaryString(new Blob([fileReaderAcc.shift()])); } }
+ } else if (fileReader.readAsArrayBuffer) {
+ // Chrome & Firefox (Spec)
+ fileReader.onloadend = function (e) { obj.xxOnSocketData(e.target.result); if (fileReaderAcc.length == 0) { fileReaderInuse = false; } else { fileReader.readAsArrayBuffer(fileReaderAcc.shift()); } }
+ }
+
+ obj.xxOnMessage = function (e) {
+ //if (obj.debugmode == 1) { console.log('Recv', e.data); }
+ //if (urlvars && urlvars['webrtctrace']) { console.log('WebRTC-Recv(' + obj.State + '): ', typeof e.data, e.data); }
+ if (typeof e.data == 'string') { if (obj.onControlMsg != null) { obj.onControlMsg(e.data); } return; } // If this is a control message, handle it here.
+ if (typeof e.data == 'object') {
+ if (fileReaderInuse == true) { fileReaderAcc.push(e.data); return; }
+ if (fileReader.readAsBinaryString) {
+ // Chrome & Firefox (Draft)
+ fileReaderInuse = true;
+ fileReader.readAsBinaryString(new Blob([e.data]));
+ } else if (f.readAsArrayBuffer) {
+ // Chrome & Firefox (Spec)
+ fileReaderInuse = true;
+ fileReader.readAsArrayBuffer(e.data);
+ } else {
+ // IE10, readAsBinaryString does not exist, use an alternative.
+ var binary = "", bytes = new Uint8Array(e.data), length = bytes.byteLength;
+ for (var i = 0; i < length; i++) { binary += String.fromCharCode(bytes[i]); }
+ obj.xxOnSocketData(binary);
+ }
+ } else {
+ // If we get a string object, it maybe the WebRTC confirm. Ignore it.
+ //obj.debug("Agent Redir Relay - OnData - " + typeof e.data + " - " + e.data.length);
+ obj.xxOnSocketData(e.data);
+ }
+ };
+
+ /*
+ obj.xxOnMessage = function (e) {
+ //if (obj.debugmode == 1) { console.log('Recv', e.data); }
+ if (urlvars && urlvars['webrtctrace']) { console.log('WebRTC-Recv(' + obj.State + '): ', typeof e.data, e.data); }
+ if (typeof e.data == 'string') { if (obj.onControlMsg != null) { obj.onControlMsg(e.data); } return; } // If this is a control message, handle it here.
+ if (typeof e.data == 'object') {
+ var f = new FileReader();
+ if (f.readAsBinaryString) {
+ // Chrome & Firefox (Draft)
+ f.onload = function (e) { obj.xxOnSocketData(e.target.result); }
+ f.readAsBinaryString(new Blob([e.data]));
+ } else if (f.readAsArrayBuffer) {
+ // Chrome & Firefox (Spec)
+ f.onloadend = function (e) { obj.xxOnSocketData(e.target.result); }
+ f.readAsArrayBuffer(e.data);
+ } else {
+ // IE10, readAsBinaryString does not exist, use an alternative.
+ var binary = '', bytes = new Uint8Array(e.data), length = bytes.byteLength;
+ for (var i = 0; i < length; i++) { binary += String.fromCharCode(bytes[i]); }
+ obj.xxOnSocketData(binary);
+ }
+ } else {
+ // If we get a string object, it maybe the WebRTC confirm. Ignore it.
+ //obj.debug("Agent Redir Relay - OnData - " + typeof e.data + " - " + e.data.length);
+ obj.xxOnSocketData(e.data);
+ }
+ };
+ */
+ obj.xxOnSocketData = function (data) {
+ if (!data) return;
+ if (typeof data === 'object') {
+ // This is an ArrayBuffer, convert it to a string array (used in IE)
+ var binary = "", bytes = new Uint8Array(data), length = bytes.byteLength;
+ for (var i = 0; i < length; i++) { binary += String.fromCharCode(bytes[i]); }
+ data = binary;
+ }
+ else if (typeof data !== 'string') return;
+ //console.log("xxOnSocketData", rstr2hex(data));
+ return obj.m.ProcessData(data);
+ }
+
+ // Send a control message over the WebRTC data channel
+ obj.sendCtrlMsg = function (x) {
+ if (typeof x == 'string') {
+ obj.webchannel.send(x);
+ if (urlvars && urlvars['webrtctrace']) { console.log('WebRTC-Send(' + obj.State + '): ', typeof x, x); }
+ if (obj.keepalive != null) obj.keepalive.sendKeepAlive();
+ }
+ }
+
+ // Send a binary message over the WebRTC data channel
+ obj.send = function (x) {
+ if (typeof x == 'string') { var b = new Uint8Array(x.length); for (var i = 0; i < x.length; ++i) { b[i] = x.charCodeAt(i); } x = b; }
+ if (urlvars && urlvars['webrtctrace']) { console.log('WebRTC-Send(' + obj.State + '): ', typeof x, x); }
+ obj.webchannel.send(x);
+ }
+
+ obj.xxStateChange = function(newstate) {
+ if (obj.State == newstate) return;
+ obj.State = newstate;
+ obj.m.xxStateChange(obj.State);
+ if (obj.onStateChanged != null) obj.onStateChanged(obj, obj.State);
+ }
+
+ obj.Stop = function () {
+ if (obj.debugmode == 1) { console.log('stop'); }
+ if (obj.rtcKeepAlive != null) { clearInterval(obj.rtcKeepAlive); obj.rtcKeepAlive = null; }
+ obj.xxStateChange(0);
+ }
+
+ obj.xxSendRtcKeepAlive = function () {
+ if (urlvars && urlvars['webrtctrace']) { console.log('WebRTC-SendKeepAlive()'); }
+ obj.sendCtrlMsg(JSON.stringify({ action: 'ping' }));
+ }
+
+ return obj;
+}
diff --git a/amt-0.2.0.js b/amt-0.2.0.js
new file mode 100644
index 0000000..76e9443
--- /dev/null
+++ b/amt-0.2.0.js
@@ -0,0 +1,987 @@
+/**
+* @fileoverview Intel(r) AMT Communication StackXX
+* @author Ylian Saint-Hilaire
+* @version v0.2.0b
+*/
+
+/**
+ * Construct a AmtStackCreateService object, this ia the main Intel AMT communication stack.
+ * @constructor
+ */
+function AmtStackCreateService(wsmanStack) {
+ var obj = new Object();
+ obj.wsman = wsmanStack;
+ obj.pfx = ["http://intel.com/wbem/wscim/1/amt-schema/1/", "http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/", "http://intel.com/wbem/wscim/1/ips-schema/1/"];
+ obj.PendingEnums = [];
+ obj.PendingBatchOperations = 0;
+ obj.ActiveEnumsCount = 0;
+ obj.MaxActiveEnumsCount = 1; // Maximum number of enumerations that can be done at the same time.
+ obj.onProcessChanged = null;
+ var _MaxProcess = 0;
+ var _LastProcess = 0;
+
+ // Return the number of pending actions
+ obj.GetPendingActions = function () { return (obj.PendingEnums.length * 2) + (obj.ActiveEnumsCount) + obj.wsman.comm.PendingAjax.length + obj.wsman.comm.ActiveAjaxCount + obj.PendingBatchOperations; }
+
+ // Private Method, Update the current processing status, this gives the application an idea of what progress is being done by the WSMAN stack
+ function _up() {
+ var x = obj.GetPendingActions();
+ if (_MaxProcess < x) _MaxProcess = x;
+ if (obj.onProcessChanged != null && _LastProcess != x) {
+ //console.log("Process Old=" + _LastProcess + ", New=" + x + ", PEnums=" + obj.PendingEnums.length + ", AEnums=" + obj.ActiveEnumsCount + ", PAjax=" + obj.wsman.comm.PendingAjax.length + ", AAjax=" + obj.wsman.comm.ActiveAjaxCount + ", PBatch=" + obj.PendingBatchOperations);
+ _LastProcess = x;
+ obj.onProcessChanged(x, _MaxProcess);
+ }
+ if (x == 0) _MaxProcess = 0;
+ }
+
+ // Perform a WSMAN "SUBSCRIBE" operation.
+ obj.Subscribe = function (name, delivery, url, callback, tag, pri, selectors, opaque, user, pass) { obj.wsman.ExecSubscribe(obj.CompleteName(name), delivery, url, function (ws, resuri, response, xstatus) { _up(); callback(obj, name, response, xstatus, tag); }, 0, pri, selectors, opaque, user, pass); _up(); }
+
+ // Perform a WSMAN "UNSUBSCRIBE" operation.
+ obj.UnSubscribe = function (name, callback, tag, pri, selectors) { obj.wsman.ExecUnSubscribe(obj.CompleteName(name), function (ws, resuri, response, xstatus) { _up(); callback(obj, name, response, xstatus, tag); }, 0, pri, selectors); _up(); }
+
+ // Perform a WSMAN "GET" operation.
+ obj.Get = function (name, callback, tag, pri) { obj.wsman.ExecGet(obj.CompleteName(name), function (ws, resuri, response, xstatus) { _up(); callback(obj, name, response, xstatus, tag); }, 0, pri); _up(); }
+
+ // Perform a WSMAN "PUT" operation.
+ obj.Put = function (name, putobj, callback, tag, pri, selectors) { obj.wsman.ExecPut(obj.CompleteName(name), putobj, function (ws, resuri, response, xstatus) { _up(); callback(obj, name, response, xstatus, tag); }, 0, pri, selectors); _up(); }
+
+ // Perform a WSMAN "CREATE" operation.
+ obj.Create = function (name, putobj, callback, tag, pri) { obj.wsman.ExecCreate(obj.CompleteName(name), putobj, function (ws, resuri, response, xstatus) { _up(); callback(obj, name, response, xstatus, tag); }, 0, pri); _up(); }
+
+ // Perform a WSMAN "DELETE" operation.
+ obj.Delete = function (name, putobj, callback, tag, pri) { obj.wsman.ExecDelete(obj.CompleteName(name), putobj, function (ws, resuri, response, xstatus) { _up(); callback(obj, name, response, xstatus, tag); }, 0, pri); _up(); }
+
+ // Perform a WSMAN method call operation.
+ obj.Exec = function (name, method, args, callback, tag, pri, selectors) { obj.wsman.ExecMethod(obj.CompleteName(name), method, args, function (ws, resuri, response, xstatus) { _up(); callback(obj, name, obj.CompleteExecResponse(response), xstatus, tag); }, 0, pri, selectors); _up(); }
+
+ // Perform a WSMAN method call operation.
+ obj.ExecWithXml = function (name, method, args, callback, tag, pri, selectors) { obj.wsman.ExecMethodXml(obj.CompleteName(name), method, execArgumentsToXml(args), function (ws, resuri, response, xstatus) { _up(); callback(obj, name, obj.CompleteExecResponse(response), xstatus, tag); }, 0, pri, selectors); _up(); }
+
+ // Perform a WSMAN "ENUMERATE" operation.
+ obj.Enum = function (name, callback, tag, pri) {
+ if (obj.ActiveEnumsCount < obj.MaxActiveEnumsCount) {
+ obj.ActiveEnumsCount++; obj.wsman.ExecEnum(obj.CompleteName(name), function (ws, resuri, response, xstatus, tag0) { _up(); _EnumStartSink(name, response, callback, resuri, xstatus, tag0); }, tag, pri);
+ } else {
+ obj.PendingEnums.push([name, callback, tag, pri]);
+ }
+ _up();
+ }
+
+ // Private method
+ function _EnumStartSink(name, response, callback, resuri, status, tag, pri) {
+ if (status != 200) { callback(obj, name, null, status, tag); _EnumDoNext(1); return; }
+ if (response == null || response.Header["Method"] != "EnumerateResponse" || !response.Body["EnumerationContext"]) { callback(obj, name, null, 603, tag); _EnumDoNext(1); return; }
+ var enumctx = response.Body["EnumerationContext"];
+ obj.wsman.ExecPull(resuri, enumctx, function (ws, resuri, response, xstatus) { _EnumContinueSink(name, response, callback, resuri, [], xstatus, tag, pri); });
+ }
+
+ // Private method
+ function _EnumContinueSink(name, response, callback, resuri, items, status, tag, pri) {
+ if (status != 200) { callback(obj, name, null, status, tag); _EnumDoNext(1); return; }
+ if (response == null || response.Header["Method"] != "PullResponse") { callback(obj, name, null, 604, tag); _EnumDoNext(1); return; }
+ for (var i in response.Body["Items"]) {
+ if (response.Body["Items"][i] instanceof Array) {
+ for (var j in response.Body["Items"][i]) { if (typeof response.Body["Items"][i][j] != 'function') { items.push(response.Body["Items"][i][j]); } }
+ } else {
+ if (typeof response.Body["Items"][i] != 'function') { items.push(response.Body["Items"][i]); }
+ }
+ }
+ if (response.Body["EnumerationContext"]) {
+ var enumctx = response.Body["EnumerationContext"];
+ obj.wsman.ExecPull(resuri, enumctx, function (ws, resuri, response, xstatus) { _EnumContinueSink(name, response, callback, resuri, items, xstatus, tag, 1); });
+ } else {
+ _EnumDoNext(1);
+ callback(obj, name, items, status, tag);
+ _up();
+ }
+ }
+
+ // Private method
+ function _EnumDoNext(dec) {
+ obj.ActiveEnumsCount -= dec;
+ if (obj.ActiveEnumsCount >= obj.MaxActiveEnumsCount || obj.PendingEnums.length == 0) { _up(); return; }
+ var x = obj.PendingEnums.shift();
+ obj.Enum(x[0], x[1], x[2]);
+ _EnumDoNext(0);
+ }
+
+ // Perform a batch of WSMAN "ENUM" operations.
+ obj.BatchEnum = function (batchname, names, callback, tag, continueOnError, pri) {
+ obj.PendingBatchOperations += (names.length * 2);
+ _BatchNextEnum(batchname, Clone(names), callback, tag, {}, continueOnError, pri); _up();
+ }
+
+ // Request each enum in the batch, stopping if something does not return status 200
+ function _BatchNextEnum(batchname, names, callback, tag, results, continueOnError, pri) {
+ obj.PendingBatchOperations -= 2;
+ var n = names.shift(), f = obj.Enum;
+ if (n[0] == '*') { f = obj.Get; n = n.substring(1); } // If the name starts with a star, do a GET instead of an ENUM. This will reduce round trips.
+ //console.log((f == obj.Get?'Get ':'Enum ') + n);
+ // Perform a GET/ENUM action
+ f(n, function (stack, name, responses, status, tag0) {
+ tag0[2][name] = { response: (responses==null?null:responses.Body), responses: responses, status: status };
+ if (tag0[1].length == 0 || status == 401 || (continueOnError != true && status != 200 && status != 400)) { obj.PendingBatchOperations -= (names.length * 2); _up(); callback(obj, batchname, tag0[2], status, tag); }
+ else { _up(); _BatchNextEnum(batchname, names, callback, tag, tag0[2], pri); }
+ }, [batchname, names, results], pri);
+ _up();
+ }
+
+ // Perform a batch of WSMAN "GET" operations.
+ obj.BatchGet = function (batchname, names, callback, tag, pri) {
+ _FetchNext({ name: batchname, names: names, callback: callback, current: 0, responses: {}, tag: tag, pri: pri }); _up();
+ }
+
+ // Private method
+ function _FetchNext(batch) {
+ if (batch.names.length <= batch.current) {
+ batch.callback(obj, batch.name, batch.responses, 200, batch.tag);
+ } else {
+ obj.wsman.ExecGet(obj.CompleteName(batch.names[batch.current]), function (ws, resuri, response, xstatus) { _Fetched(batch, response, xstatus); }, batch.pri);
+ batch.current++;
+ }
+ _up();
+ }
+
+ // Private method
+ function _Fetched(batch, response, status) {
+ if (response == null || status != 200) {
+ batch.callback(obj, batch.name, null, status, batch.tag);
+ } else {
+ batch.responses[response.Header["Method"]] = response;
+ _FetchNext(batch);
+ }
+ }
+
+ // Private method
+ obj.CompleteName = function(name) {
+ if (name.indexOf("AMT_") == 0) return obj.pfx[0] + name;
+ if (name.indexOf("CIM_") == 0) return obj.pfx[1] + name;
+ if (name.indexOf("IPS_") == 0) return obj.pfx[2] + name;
+ }
+
+ obj.CompleteExecResponse = function (resp) {
+ if (resp && resp != null && resp.Body && (resp.Body["ReturnValue"] != undefined)) { resp.Body.ReturnValueStr = obj.AmtStatusToStr(resp.Body["ReturnValue"]); }
+ return resp;
+ }
+
+ obj.RequestPowerStateChange = function (PowerState, callback_func) {
+ obj.CIM_PowerManagementService_RequestPowerStateChange(PowerState, "http://schemas.xmlsoap.org/ws/2004/08/addressing http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ComputerSystem CIM_ComputerSystem ManagedSystem ", null, null, callback_func);
+ }
+
+ obj.RequestOSPowerStateChange = function (PowerState, callback_func) {
+ obj.IPS_PowerManagementService_RequestOSPowerSavingStateChange(PowerState, "http://schemas.xmlsoap.org/ws/2004/08/addressing http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ComputerSystem CIM_ComputerSystem ManagedSystem ", null, null, callback_func);
+ }
+
+ obj.SetBootConfigRole = function (Role, callback_func) {
+ obj.CIM_BootService_SetBootConfigRole("http://schemas.xmlsoap.org/ws/2004/08/addressing http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_BootConfigSetting Intel(r) AMT: Boot Configuration 0 ", Role, callback_func);
+ }
+
+ // Cancel all pending queries with given status
+ obj.CancelAllQueries = function (s) {
+ obj.wsman.CancelAllQueries(s);
+ }
+
+ // Auto generated methods
+ obj.AMT_AgentPresenceWatchdog_RegisterAgent = function (callback_func) { obj.Exec("AMT_AgentPresenceWatchdog", "RegisterAgent", {}, callback_func); }
+ obj.AMT_AgentPresenceWatchdog_AssertPresence = function (SequenceNumber, callback_func) { obj.Exec("AMT_AgentPresenceWatchdog", "AssertPresence", { "SequenceNumber": SequenceNumber }, callback_func); }
+ obj.AMT_AgentPresenceWatchdog_AssertShutdown = function (SequenceNumber, callback_func) { obj.Exec("AMT_AgentPresenceWatchdog", "AssertShutdown", { "SequenceNumber": SequenceNumber }, callback_func); }
+ obj.AMT_AgentPresenceWatchdog_AddAction = function (OldState, NewState, EventOnTransition, ActionSd, ActionEac, callback_func, tag, pri, selectors) { obj.Exec("AMT_AgentPresenceWatchdog", "AddAction", { "OldState": OldState, "NewState": NewState, "EventOnTransition": EventOnTransition, "ActionSd": ActionSd, "ActionEac": ActionEac }, callback_func, tag, pri, selectors); }
+ obj.AMT_AgentPresenceWatchdog_DeleteAllActions = function (callback_func, tag, pri, selectors) { obj.Exec("AMT_AgentPresenceWatchdog", "DeleteAllActions", {}, callback_func, tag, pri, selectors); }
+ obj.AMT_AgentPresenceWatchdogAction_GetActionEac = function (callback_func) { obj.Exec("AMT_AgentPresenceWatchdogAction", "GetActionEac", {}, callback_func); }
+ obj.AMT_AgentPresenceWatchdogVA_RegisterAgent = function (callback_func) { obj.Exec("AMT_AgentPresenceWatchdogVA", "RegisterAgent", {}, callback_func); }
+ obj.AMT_AgentPresenceWatchdogVA_AssertPresence = function (SequenceNumber, callback_func) { obj.Exec("AMT_AgentPresenceWatchdogVA", "AssertPresence", { "SequenceNumber": SequenceNumber }, callback_func); }
+ obj.AMT_AgentPresenceWatchdogVA_AssertShutdown = function (SequenceNumber, callback_func) { obj.Exec("AMT_AgentPresenceWatchdogVA", "AssertShutdown", { "SequenceNumber": SequenceNumber }, callback_func); }
+ obj.AMT_AgentPresenceWatchdogVA_AddAction = function (OldState, NewState, EventOnTransition, ActionSd, ActionEac, callback_func) { obj.Exec("AMT_AgentPresenceWatchdogVA", "AddAction", { "OldState": OldState, "NewState": NewState, "EventOnTransition": EventOnTransition, "ActionSd": ActionSd, "ActionEac": ActionEac }, callback_func); }
+ obj.AMT_AgentPresenceWatchdogVA_DeleteAllActions = function (_method_dummy, callback_func) { obj.Exec("AMT_AgentPresenceWatchdogVA", "DeleteAllActions", { "_method_dummy": _method_dummy }, callback_func); }
+ obj.AMT_AuditLog_ClearLog = function (callback_func) { obj.Exec("AMT_AuditLog", "ClearLog", {}, callback_func); }
+ obj.AMT_AuditLog_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("AMT_AuditLog", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
+ obj.AMT_AuditLog_ReadRecords = function (StartIndex, callback_func, tag) { obj.Exec("AMT_AuditLog", "ReadRecords", { "StartIndex": StartIndex }, callback_func, tag); }
+ obj.AMT_AuditLog_SetAuditLock = function (LockTimeoutInSeconds, Flag, Handle, callback_func) { obj.Exec("AMT_AuditLog", "SetAuditLock", { "LockTimeoutInSeconds": LockTimeoutInSeconds, "Flag": Flag, "Handle": Handle }, callback_func); }
+ obj.AMT_AuditLog_ExportAuditLogSignature = function (SigningMechanism, callback_func) { obj.Exec("AMT_AuditLog", "ExportAuditLogSignature", { "SigningMechanism": SigningMechanism }, callback_func); }
+ obj.AMT_AuditLog_SetSigningKeyMaterial = function (SigningMechanismType, SigningKey, LengthOfCertificates, Certificates, callback_func) { obj.Exec("AMT_AuditLog", "SetSigningKeyMaterial", { "SigningMechanismType": SigningMechanismType, "SigningKey": SigningKey, "LengthOfCertificates": LengthOfCertificates, "Certificates": Certificates }, callback_func); }
+ obj.AMT_AuditPolicyRule_SetAuditPolicy = function (Enable, AuditedAppID, EventID, PolicyType, callback_func) { obj.Exec("AMT_AuditPolicyRule", "SetAuditPolicy", { "Enable": Enable, "AuditedAppID": AuditedAppID, "EventID": EventID, "PolicyType": PolicyType }, callback_func); }
+ obj.AMT_AuditPolicyRule_SetAuditPolicyBulk = function (Enable, AuditedAppID, EventID, PolicyType, callback_func) { obj.Exec("AMT_AuditPolicyRule", "SetAuditPolicyBulk", { "Enable": Enable, "AuditedAppID": AuditedAppID, "EventID": EventID, "PolicyType": PolicyType }, callback_func); }
+ obj.AMT_AuthorizationService_AddUserAclEntryEx = function (DigestUsername, DigestPassword, KerberosUserSid, AccessPermission, Realms, callback_func) { obj.Exec("AMT_AuthorizationService", "AddUserAclEntryEx", { "DigestUsername": DigestUsername, "DigestPassword": DigestPassword, "KerberosUserSid": KerberosUserSid, "AccessPermission": AccessPermission, "Realms": Realms }, callback_func); }
+ obj.AMT_AuthorizationService_EnumerateUserAclEntries = function (StartIndex, callback_func) { obj.Exec("AMT_AuthorizationService", "EnumerateUserAclEntries", { "StartIndex": StartIndex }, callback_func); }
+ obj.AMT_AuthorizationService_GetUserAclEntryEx = function (Handle, callback_func, tag) { obj.Exec("AMT_AuthorizationService", "GetUserAclEntryEx", { "Handle": Handle }, callback_func, tag); }
+ obj.AMT_AuthorizationService_UpdateUserAclEntryEx = function (Handle, DigestUsername, DigestPassword, KerberosUserSid, AccessPermission, Realms, callback_func) { obj.Exec("AMT_AuthorizationService", "UpdateUserAclEntryEx", { "Handle": Handle, "DigestUsername": DigestUsername, "DigestPassword": DigestPassword, "KerberosUserSid": KerberosUserSid, "AccessPermission": AccessPermission, "Realms": Realms }, callback_func); }
+ obj.AMT_AuthorizationService_RemoveUserAclEntry = function (Handle, callback_func) { obj.Exec("AMT_AuthorizationService", "RemoveUserAclEntry", { "Handle": Handle }, callback_func); }
+ obj.AMT_AuthorizationService_SetAdminAclEntryEx = function (Username, DigestPassword, callback_func) { obj.Exec("AMT_AuthorizationService", "SetAdminAclEntryEx", { "Username": Username, "DigestPassword": DigestPassword }, callback_func); }
+ obj.AMT_AuthorizationService_GetAdminAclEntry = function (callback_func) { obj.Exec("AMT_AuthorizationService", "GetAdminAclEntry", {}, callback_func); }
+ obj.AMT_AuthorizationService_GetAdminAclEntryStatus = function (callback_func) { obj.Exec("AMT_AuthorizationService", "GetAdminAclEntryStatus", {}, callback_func); }
+ obj.AMT_AuthorizationService_GetAdminNetAclEntryStatus = function (callback_func) { obj.Exec("AMT_AuthorizationService", "GetAdminNetAclEntryStatus", {}, callback_func); }
+ obj.AMT_AuthorizationService_SetAclEnabledState = function (Handle, Enabled, callback_func, tag) { obj.Exec("AMT_AuthorizationService", "SetAclEnabledState", { "Handle": Handle, "Enabled": Enabled }, callback_func, tag); }
+ obj.AMT_AuthorizationService_GetAclEnabledState = function (Handle, callback_func, tag) { obj.Exec("AMT_AuthorizationService", "GetAclEnabledState", { "Handle": Handle }, callback_func, tag); }
+ obj.AMT_EndpointAccessControlService_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("AMT_EndpointAccessControlService", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
+ obj.AMT_EndpointAccessControlService_GetPosture = function (PostureType, callback_func) { obj.Exec("AMT_EndpointAccessControlService", "GetPosture", { "PostureType": PostureType }, callback_func); }
+ obj.AMT_EndpointAccessControlService_GetPostureHash = function (PostureType, callback_func) { obj.Exec("AMT_EndpointAccessControlService", "GetPostureHash", { "PostureType": PostureType }, callback_func); }
+ obj.AMT_EndpointAccessControlService_UpdatePostureState = function (UpdateType, callback_func) { obj.Exec("AMT_EndpointAccessControlService", "UpdatePostureState", { "UpdateType": UpdateType }, callback_func); }
+ obj.AMT_EndpointAccessControlService_GetEacOptions = function (callback_func) { obj.Exec("AMT_EndpointAccessControlService", "GetEacOptions", {}, callback_func); }
+ obj.AMT_EndpointAccessControlService_SetEacOptions = function (EacVendors, PostureHashAlgorithm, callback_func) { obj.Exec("AMT_EndpointAccessControlService", "SetEacOptions", { "EacVendors": EacVendors, "PostureHashAlgorithm": PostureHashAlgorithm }, callback_func); }
+ obj.AMT_EnvironmentDetectionSettingData_SetSystemDefensePolicy = function (Policy, callback_func) { obj.Exec("AMT_EnvironmentDetectionSettingData", "SetSystemDefensePolicy", { "Policy": Policy }, callback_func); }
+ obj.AMT_EnvironmentDetectionSettingData_EnableVpnRouting = function (Enable, callback_func) { obj.Exec("AMT_EnvironmentDetectionSettingData", "EnableVpnRouting", { "Enable": Enable }, callback_func); }
+ obj.AMT_EthernetPortSettings_SetLinkPreference = function (LinkPreference, Timeout, callback_func) { obj.Exec("AMT_EthernetPortSettings", "SetLinkPreference", { "LinkPreference": LinkPreference, "Timeout": Timeout }, callback_func); }
+ obj.AMT_HeuristicPacketFilterStatistics_ResetSelectedStats = function (SelectedStatistics, callback_func) { obj.Exec("AMT_HeuristicPacketFilterStatistics", "ResetSelectedStats", { "SelectedStatistics": SelectedStatistics }, callback_func); }
+ obj.AMT_KerberosSettingData_GetCredentialCacheState = function (callback_func) { obj.Exec("AMT_KerberosSettingData", "GetCredentialCacheState", {}, callback_func); }
+ obj.AMT_KerberosSettingData_SetCredentialCacheState = function (Enable, callback_func) { obj.Exec("AMT_KerberosSettingData", "SetCredentialCacheState", { "Enable": Enable }, callback_func); }
+ obj.AMT_MessageLog_CancelIteration = function (IterationIdentifier, callback_func) { obj.Exec("AMT_MessageLog", "CancelIteration", { "IterationIdentifier": IterationIdentifier }, callback_func); }
+ obj.AMT_MessageLog_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("AMT_MessageLog", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
+ obj.AMT_MessageLog_ClearLog = function (callback_func) { obj.Exec("AMT_MessageLog", "ClearLog", { }, callback_func); }
+ obj.AMT_MessageLog_GetRecords = function (IterationIdentifier, MaxReadRecords, callback_func, tag) { obj.Exec("AMT_MessageLog", "GetRecords", { "IterationIdentifier": IterationIdentifier, "MaxReadRecords": MaxReadRecords }, callback_func, tag); }
+ obj.AMT_MessageLog_GetRecord = function (IterationIdentifier, PositionToNext, callback_func) { obj.Exec("AMT_MessageLog", "GetRecord", { "IterationIdentifier": IterationIdentifier, "PositionToNext": PositionToNext }, callback_func); }
+ obj.AMT_MessageLog_PositionAtRecord = function (IterationIdentifier, MoveAbsolute, RecordNumber, callback_func) { obj.Exec("AMT_MessageLog", "PositionAtRecord", { "IterationIdentifier": IterationIdentifier, "MoveAbsolute": MoveAbsolute, "RecordNumber": RecordNumber }, callback_func); }
+ obj.AMT_MessageLog_PositionToFirstRecord = function (callback_func, tag) { obj.Exec("AMT_MessageLog", "PositionToFirstRecord", {}, callback_func, tag); }
+ obj.AMT_MessageLog_FreezeLog = function (Freeze, callback_func) { obj.Exec("AMT_MessageLog", "FreezeLog", { "Freeze": Freeze }, callback_func); }
+ obj.AMT_PublicKeyManagementService_AddCRL = function (Url, SerialNumbers, callback_func) { obj.Exec("AMT_PublicKeyManagementService", "AddCRL", { "Url": Url, "SerialNumbers": SerialNumbers }, callback_func); }
+ obj.AMT_PublicKeyManagementService_ResetCRLList = function (_method_dummy, callback_func) { obj.Exec("AMT_PublicKeyManagementService", "ResetCRLList", { "_method_dummy": _method_dummy }, callback_func); }
+ obj.AMT_PublicKeyManagementService_AddCertificate = function (CertificateBlob, callback_func) { obj.Exec("AMT_PublicKeyManagementService", "AddCertificate", { "CertificateBlob": CertificateBlob }, callback_func); }
+ obj.AMT_PublicKeyManagementService_AddTrustedRootCertificate = function (CertificateBlob, callback_func) { obj.Exec("AMT_PublicKeyManagementService", "AddTrustedRootCertificate", { "CertificateBlob": CertificateBlob }, callback_func); }
+ obj.AMT_PublicKeyManagementService_AddKey = function (KeyBlob, callback_func) { obj.Exec("AMT_PublicKeyManagementService", "AddKey", { "KeyBlob": KeyBlob }, callback_func); }
+ obj.AMT_PublicKeyManagementService_GeneratePKCS10Request = function (KeyPair, DNName, Usage, callback_func) { obj.Exec("AMT_PublicKeyManagementService", "GeneratePKCS10Request", { "KeyPair": KeyPair, "DNName": DNName, "Usage": Usage }, callback_func); }
+ obj.AMT_PublicKeyManagementService_GeneratePKCS10RequestEx = function (KeyPair, SigningAlgorithm, NullSignedCertificateRequest, callback_func) { obj.Exec("AMT_PublicKeyManagementService", "GeneratePKCS10RequestEx", { "KeyPair": KeyPair, "SigningAlgorithm": SigningAlgorithm, "NullSignedCertificateRequest": NullSignedCertificateRequest }, callback_func); }
+ obj.AMT_PublicKeyManagementService_GenerateKeyPair = function (KeyAlgorithm, KeyLength, callback_func) { obj.Exec("AMT_PublicKeyManagementService", "GenerateKeyPair", { "KeyAlgorithm": KeyAlgorithm, "KeyLength": KeyLength }, callback_func); }
+ obj.AMT_RedirectionService_RequestStateChange = function (RequestedState, callback_func) { obj.Exec("AMT_RedirectionService", "RequestStateChange", { "RequestedState": RequestedState }, callback_func); }
+ obj.AMT_RedirectionService_TerminateSession = function (SessionType, callback_func) { obj.Exec("AMT_RedirectionService", "TerminateSession", { "SessionType": SessionType }, callback_func); }
+ obj.AMT_RemoteAccessService_AddMpServer = function (AccessInfo, InfoFormat, Port, AuthMethod, Certificate, Username, Password, CN, callback_func) { obj.Exec("AMT_RemoteAccessService", "AddMpServer", { "AccessInfo": AccessInfo, "InfoFormat": InfoFormat, "Port": Port, "AuthMethod": AuthMethod, "Certificate": Certificate, "Username": Username, "Password": Password, "CN": CN }, callback_func); }
+ obj.AMT_RemoteAccessService_AddRemoteAccessPolicyRule = function (Trigger, TunnelLifeTime, ExtendedData, MpServer, InternalMpServer, callback_func) { obj.Exec("AMT_RemoteAccessService", "AddRemoteAccessPolicyRule", { "Trigger": Trigger, "TunnelLifeTime": TunnelLifeTime, "ExtendedData": ExtendedData, "MpServer": MpServer, "InternalMpServer": InternalMpServer }, callback_func); }
+ obj.AMT_RemoteAccessService_CloseRemoteAccessConnection = function (_method_dummy, callback_func) { obj.Exec("AMT_RemoteAccessService", "CloseRemoteAccessConnection", { "_method_dummy": _method_dummy }, callback_func); }
+ obj.AMT_SetupAndConfigurationService_CommitChanges = function (_method_dummy, callback_func) { obj.Exec("AMT_SetupAndConfigurationService", "CommitChanges", { "_method_dummy": _method_dummy }, callback_func); }
+ obj.AMT_SetupAndConfigurationService_Unprovision = function (ProvisioningMode, callback_func) { obj.Exec("AMT_SetupAndConfigurationService", "Unprovision", { "ProvisioningMode": ProvisioningMode }, callback_func); }
+ obj.AMT_SetupAndConfigurationService_PartialUnprovision = function (_method_dummy, callback_func) { obj.Exec("AMT_SetupAndConfigurationService", "PartialUnprovision", { "_method_dummy": _method_dummy }, callback_func); }
+ obj.AMT_SetupAndConfigurationService_ResetFlashWearOutProtection = function (_method_dummy, callback_func) { obj.Exec("AMT_SetupAndConfigurationService", "ResetFlashWearOutProtection", { "_method_dummy": _method_dummy }, callback_func); }
+ obj.AMT_SetupAndConfigurationService_ExtendProvisioningPeriod = function (Duration, callback_func) { obj.Exec("AMT_SetupAndConfigurationService", "ExtendProvisioningPeriod", { "Duration": Duration }, callback_func); }
+ obj.AMT_SetupAndConfigurationService_SetMEBxPassword = function (Password, callback_func) { obj.Exec("AMT_SetupAndConfigurationService", "SetMEBxPassword", { "Password": Password }, callback_func); }
+ obj.AMT_SetupAndConfigurationService_SetTLSPSK = function (PID, PPS, callback_func) { obj.Exec("AMT_SetupAndConfigurationService", "SetTLSPSK", { "PID": PID, "PPS": PPS }, callback_func); }
+ obj.AMT_SetupAndConfigurationService_GetProvisioningAuditRecord = function (callback_func) { obj.Exec("AMT_SetupAndConfigurationService", "GetProvisioningAuditRecord", {}, callback_func); }
+ obj.AMT_SetupAndConfigurationService_GetUuid = function (callback_func) { obj.Exec("AMT_SetupAndConfigurationService", "GetUuid", {}, callback_func); }
+ obj.AMT_SetupAndConfigurationService_GetUnprovisionBlockingComponents = function (callback_func) { obj.Exec("AMT_SetupAndConfigurationService", "GetUnprovisionBlockingComponents", {}, callback_func); }
+ obj.AMT_SetupAndConfigurationService_GetProvisioningAuditRecordV2 = function (callback_func) { obj.Exec("AMT_SetupAndConfigurationService", "GetProvisioningAuditRecordV2", {}, callback_func); }
+ obj.AMT_SystemDefensePolicy_GetTimeout = function (callback_func) { obj.Exec("AMT_SystemDefensePolicy", "GetTimeout", {}, callback_func); }
+ obj.AMT_SystemDefensePolicy_SetTimeout = function (Timeout, callback_func) { obj.Exec("AMT_SystemDefensePolicy", "SetTimeout", { "Timeout": Timeout }, callback_func); }
+ obj.AMT_SystemDefensePolicy_UpdateStatistics = function (NetworkInterface, ResetOnRead, callback_func, tag, pri, selectors) { obj.Exec("AMT_SystemDefensePolicy", "UpdateStatistics", { "NetworkInterface": NetworkInterface, "ResetOnRead": ResetOnRead }, callback_func, tag, pri, selectors); }
+ obj.AMT_SystemPowerScheme_SetPowerScheme = function (callback_func, schemeInstanceId, tag) { obj.Exec("AMT_SystemPowerScheme", "SetPowerScheme", {}, callback_func, tag, 0, { "InstanceID": schemeInstanceId }); }
+ obj.AMT_TimeSynchronizationService_GetLowAccuracyTimeSynch = function (callback_func, tag) { obj.Exec("AMT_TimeSynchronizationService", "GetLowAccuracyTimeSynch", {}, callback_func, tag); }
+ obj.AMT_TimeSynchronizationService_SetHighAccuracyTimeSynch = function (Ta0, Tm1, Tm2, callback_func, tag) { obj.Exec("AMT_TimeSynchronizationService", "SetHighAccuracyTimeSynch", { "Ta0": Ta0, "Tm1": Tm1, "Tm2": Tm2 }, callback_func, tag); }
+ obj.AMT_UserInitiatedConnectionService_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("AMT_UserInitiatedConnectionService", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
+ obj.AMT_WebUIService_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("AMT_WebUIService", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
+ obj.AMT_WiFiPortConfigurationService_AddWiFiSettings = function (WiFiEndpoint, WiFiEndpointSettingsInput, IEEE8021xSettingsInput, ClientCredential, CACredential, callback_func) { obj.ExecWithXml("AMT_WiFiPortConfigurationService", "AddWiFiSettings", { "WiFiEndpoint": WiFiEndpoint, "WiFiEndpointSettingsInput": WiFiEndpointSettingsInput, "IEEE8021xSettingsInput": IEEE8021xSettingsInput, "ClientCredential": ClientCredential, "CACredential": CACredential }, callback_func); }
+ obj.AMT_WiFiPortConfigurationService_UpdateWiFiSettings = function (WiFiEndpointSettings, WiFiEndpointSettingsInput, IEEE8021xSettingsInput, ClientCredential, CACredential, callback_func) { obj.ExecWithXml("AMT_WiFiPortConfigurationService", "UpdateWiFiSettings", { "WiFiEndpointSettings": WiFiEndpointSettings, "WiFiEndpointSettingsInput": WiFiEndpointSettingsInput, "IEEE8021xSettingsInput": IEEE8021xSettingsInput, "ClientCredential": ClientCredential, "CACredential": CACredential }, callback_func); }
+ obj.AMT_WiFiPortConfigurationService_DeleteAllITProfiles = function (_method_dummy, callback_func) { obj.Exec("AMT_WiFiPortConfigurationService", "DeleteAllITProfiles", { "_method_dummy": _method_dummy }, callback_func); }
+ obj.AMT_WiFiPortConfigurationService_DeleteAllUserProfiles = function (_method_dummy, callback_func) { obj.Exec("AMT_WiFiPortConfigurationService", "DeleteAllUserProfiles", { "_method_dummy": _method_dummy }, callback_func); }
+ obj.CIM_Account_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("CIM_Account", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
+ obj.CIM_AccountManagementService_CreateAccount = function (System, AccountTemplate, callback_func) { obj.Exec("CIM_AccountManagementService", "CreateAccount", { "System": System, "AccountTemplate": AccountTemplate }, callback_func); }
+ obj.CIM_BootConfigSetting_ChangeBootOrder = function (Source, callback_func) { obj.Exec("CIM_BootConfigSetting", "ChangeBootOrder", { "Source": Source }, callback_func); }
+ obj.CIM_BootService_SetBootConfigRole = function (BootConfigSetting, Role, callback_func) { obj.Exec("CIM_BootService", "SetBootConfigRole", { "BootConfigSetting": BootConfigSetting, "Role": Role }, callback_func, 0, 1); }
+ obj.CIM_Card_ConnectorPower = function (Connector, PoweredOn, callback_func) { obj.Exec("CIM_Card", "ConnectorPower", { "Connector": Connector, "PoweredOn": PoweredOn }, callback_func); }
+ obj.CIM_Card_IsCompatible = function (ElementToCheck, callback_func) { obj.Exec("CIM_Card", "IsCompatible", { "ElementToCheck": ElementToCheck }, callback_func); }
+ obj.CIM_Chassis_IsCompatible = function (ElementToCheck, callback_func) { obj.Exec("CIM_Chassis", "IsCompatible", { "ElementToCheck": ElementToCheck }, callback_func); }
+ obj.CIM_Fan_SetSpeed = function (DesiredSpeed, callback_func) { obj.Exec("CIM_Fan", "SetSpeed", { "DesiredSpeed": DesiredSpeed }, callback_func); }
+ obj.CIM_KVMRedirectionSAP_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("CIM_KVMRedirectionSAP", "RequestStateChange", { "RequestedState": RequestedState/*, "TimeoutPeriod": TimeoutPeriod */}, callback_func); }
+ obj.CIM_MediaAccessDevice_LockMedia = function (Lock, callback_func) { obj.Exec("CIM_MediaAccessDevice", "LockMedia", { "Lock": Lock }, callback_func); }
+ obj.CIM_MediaAccessDevice_SetPowerState = function (PowerState, Time, callback_func) { obj.Exec("CIM_MediaAccessDevice", "SetPowerState", { "PowerState": PowerState, "Time": Time }, callback_func); }
+ obj.CIM_MediaAccessDevice_Reset = function (callback_func) { obj.Exec("CIM_MediaAccessDevice", "Reset", {}, callback_func); }
+ obj.CIM_MediaAccessDevice_EnableDevice = function (Enabled, callback_func) { obj.Exec("CIM_MediaAccessDevice", "EnableDevice", { "Enabled": Enabled }, callback_func); }
+ obj.CIM_MediaAccessDevice_OnlineDevice = function (Online, callback_func) { obj.Exec("CIM_MediaAccessDevice", "OnlineDevice", { "Online": Online }, callback_func); }
+ obj.CIM_MediaAccessDevice_QuiesceDevice = function (Quiesce, callback_func) { obj.Exec("CIM_MediaAccessDevice", "QuiesceDevice", { "Quiesce": Quiesce }, callback_func); }
+ obj.CIM_MediaAccessDevice_SaveProperties = function (callback_func) { obj.Exec("CIM_MediaAccessDevice", "SaveProperties", {}, callback_func); }
+ obj.CIM_MediaAccessDevice_RestoreProperties = function (callback_func) { obj.Exec("CIM_MediaAccessDevice", "RestoreProperties", {}, callback_func); }
+ obj.CIM_MediaAccessDevice_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("CIM_MediaAccessDevice", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
+ obj.CIM_PhysicalFrame_IsCompatible = function (ElementToCheck, callback_func) { obj.Exec("CIM_PhysicalFrame", "IsCompatible", { "ElementToCheck": ElementToCheck }, callback_func); }
+ obj.CIM_PhysicalPackage_IsCompatible = function (ElementToCheck, callback_func) { obj.Exec("CIM_PhysicalPackage", "IsCompatible", { "ElementToCheck": ElementToCheck }, callback_func); }
+ obj.CIM_PowerManagementService_RequestPowerStateChange = function (PowerState, ManagedElement, Time, TimeoutPeriod, callback_func) { obj.Exec("CIM_PowerManagementService", "RequestPowerStateChange", { "PowerState": PowerState, "ManagedElement": ManagedElement, "Time": Time, "TimeoutPeriod": TimeoutPeriod }, callback_func, 0, 1); }
+ obj.CIM_PowerSupply_SetPowerState = function (PowerState, Time, callback_func) { obj.Exec("CIM_PowerSupply", "SetPowerState", { "PowerState": PowerState, "Time": Time }, callback_func); }
+ obj.CIM_PowerSupply_Reset = function (callback_func) { obj.Exec("CIM_PowerSupply", "Reset", {}, callback_func); }
+ obj.CIM_PowerSupply_EnableDevice = function (Enabled, callback_func) { obj.Exec("CIM_PowerSupply", "EnableDevice", { "Enabled": Enabled }, callback_func); }
+ obj.CIM_PowerSupply_OnlineDevice = function (Online, callback_func) { obj.Exec("CIM_PowerSupply", "OnlineDevice", { "Online": Online }, callback_func); }
+ obj.CIM_PowerSupply_QuiesceDevice = function (Quiesce, callback_func) { obj.Exec("CIM_PowerSupply", "QuiesceDevice", { "Quiesce": Quiesce }, callback_func); }
+ obj.CIM_PowerSupply_SaveProperties = function (callback_func) { obj.Exec("CIM_PowerSupply", "SaveProperties", {}, callback_func); }
+ obj.CIM_PowerSupply_RestoreProperties = function (callback_func) { obj.Exec("CIM_PowerSupply", "RestoreProperties", {}, callback_func); }
+ obj.CIM_PowerSupply_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("CIM_PowerSupply", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
+ obj.CIM_Processor_SetPowerState = function (PowerState, Time, callback_func) { obj.Exec("CIM_Processor", "SetPowerState", { "PowerState": PowerState, "Time": Time }, callback_func); }
+ obj.CIM_Processor_Reset = function (callback_func) { obj.Exec("CIM_Processor", "Reset", {}, callback_func); }
+ obj.CIM_Processor_EnableDevice = function (Enabled, callback_func) { obj.Exec("CIM_Processor", "EnableDevice", { "Enabled": Enabled }, callback_func); }
+ obj.CIM_Processor_OnlineDevice = function (Online, callback_func) { obj.Exec("CIM_Processor", "OnlineDevice", { "Online": Online }, callback_func); }
+ obj.CIM_Processor_QuiesceDevice = function (Quiesce, callback_func) { obj.Exec("CIM_Processor", "QuiesceDevice", { "Quiesce": Quiesce }, callback_func); }
+ obj.CIM_Processor_SaveProperties = function (callback_func) { obj.Exec("CIM_Processor", "SaveProperties", {}, callback_func); }
+ obj.CIM_Processor_RestoreProperties = function (callback_func) { obj.Exec("CIM_Processor", "RestoreProperties", {}, callback_func); }
+ obj.CIM_Processor_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("CIM_Processor", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
+ obj.CIM_RecordLog_ClearLog = function (callback_func) { obj.Exec("CIM_RecordLog", "ClearLog", {}, callback_func); }
+ obj.CIM_RecordLog_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("CIM_RecordLog", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
+ obj.CIM_RedirectionService_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("CIM_RedirectionService", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
+ obj.CIM_Sensor_SetPowerState = function (PowerState, Time, callback_func) { obj.Exec("CIM_Sensor", "SetPowerState", { "PowerState": PowerState, "Time": Time }, callback_func); }
+ obj.CIM_Sensor_Reset = function (callback_func) { obj.Exec("CIM_Sensor", "Reset", {}, callback_func); }
+ obj.CIM_Sensor_EnableDevice = function (Enabled, callback_func) { obj.Exec("CIM_Sensor", "EnableDevice", { "Enabled": Enabled }, callback_func); }
+ obj.CIM_Sensor_OnlineDevice = function (Online, callback_func) { obj.Exec("CIM_Sensor", "OnlineDevice", { "Online": Online }, callback_func); }
+ obj.CIM_Sensor_QuiesceDevice = function (Quiesce, callback_func) { obj.Exec("CIM_Sensor", "QuiesceDevice", { "Quiesce": Quiesce }, callback_func); }
+ obj.CIM_Sensor_SaveProperties = function (callback_func) { obj.Exec("CIM_Sensor", "SaveProperties", {}, callback_func); }
+ obj.CIM_Sensor_RestoreProperties = function (callback_func) { obj.Exec("CIM_Sensor", "RestoreProperties", {}, callback_func); }
+ obj.CIM_Sensor_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("CIM_Sensor", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
+ obj.CIM_StatisticalData_ResetSelectedStats = function (SelectedStatistics, callback_func) { obj.Exec("CIM_StatisticalData", "ResetSelectedStats", { "SelectedStatistics": SelectedStatistics }, callback_func); }
+ obj.CIM_Watchdog_KeepAlive = function (callback_func) { obj.Exec("CIM_Watchdog", "KeepAlive", {}, callback_func); }
+ obj.CIM_Watchdog_SetPowerState = function (PowerState, Time, callback_func) { obj.Exec("CIM_Watchdog", "SetPowerState", { "PowerState": PowerState, "Time": Time }, callback_func); }
+ obj.CIM_Watchdog_Reset = function (callback_func) { obj.Exec("CIM_Watchdog", "Reset", {}, callback_func); }
+ obj.CIM_Watchdog_EnableDevice = function (Enabled, callback_func) { obj.Exec("CIM_Watchdog", "EnableDevice", { "Enabled": Enabled }, callback_func); }
+ obj.CIM_Watchdog_OnlineDevice = function (Online, callback_func) { obj.Exec("CIM_Watchdog", "OnlineDevice", { "Online": Online }, callback_func); }
+ obj.CIM_Watchdog_QuiesceDevice = function (Quiesce, callback_func) { obj.Exec("CIM_Watchdog", "QuiesceDevice", { "Quiesce": Quiesce }, callback_func); }
+ obj.CIM_Watchdog_SaveProperties = function (callback_func) { obj.Exec("CIM_Watchdog", "SaveProperties", {}, callback_func); }
+ obj.CIM_Watchdog_RestoreProperties = function (callback_func) { obj.Exec("CIM_Watchdog", "RestoreProperties", {}, callback_func); }
+ obj.CIM_Watchdog_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("CIM_Watchdog", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
+ obj.CIM_WiFiPort_SetPowerState = function (PowerState, Time, callback_func) { obj.Exec("CIM_WiFiPort", "SetPowerState", { "PowerState": PowerState, "Time": Time }, callback_func); }
+ obj.CIM_WiFiPort_Reset = function (callback_func) { obj.Exec("CIM_WiFiPort", "Reset", {}, callback_func); }
+ obj.CIM_WiFiPort_EnableDevice = function (Enabled, callback_func) { obj.Exec("CIM_WiFiPort", "EnableDevice", { "Enabled": Enabled }, callback_func); }
+ obj.CIM_WiFiPort_OnlineDevice = function (Online, callback_func) { obj.Exec("CIM_WiFiPort", "OnlineDevice", { "Online": Online }, callback_func); }
+ obj.CIM_WiFiPort_QuiesceDevice = function (Quiesce, callback_func) { obj.Exec("CIM_WiFiPort", "QuiesceDevice", { "Quiesce": Quiesce }, callback_func); }
+ obj.CIM_WiFiPort_SaveProperties = function (callback_func) { obj.Exec("CIM_WiFiPort", "SaveProperties", {}, callback_func); }
+ obj.CIM_WiFiPort_RestoreProperties = function (callback_func) { obj.Exec("CIM_WiFiPort", "RestoreProperties", {}, callback_func); }
+ obj.CIM_WiFiPort_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("CIM_WiFiPort", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
+ obj.IPS_HostBasedSetupService_Setup = function (NetAdminPassEncryptionType, NetworkAdminPassword, McNonce, Certificate, SigningAlgorithm, DigitalSignature, callback_func) { obj.Exec("IPS_HostBasedSetupService", "Setup", { "NetAdminPassEncryptionType": NetAdminPassEncryptionType, "NetworkAdminPassword": NetworkAdminPassword, "McNonce": McNonce, "Certificate": Certificate, "SigningAlgorithm": SigningAlgorithm, "DigitalSignature": DigitalSignature }, callback_func); }
+ obj.IPS_HostBasedSetupService_AddNextCertInChain = function (NextCertificate, IsLeafCertificate, IsRootCertificate, callback_func) { obj.Exec("IPS_HostBasedSetupService", "AddNextCertInChain", { "NextCertificate": NextCertificate, "IsLeafCertificate": IsLeafCertificate, "IsRootCertificate": IsRootCertificate }, callback_func); }
+ obj.IPS_HostBasedSetupService_AdminSetup = function (NetAdminPassEncryptionType, NetworkAdminPassword, McNonce, SigningAlgorithm, DigitalSignature, callback_func) { obj.Exec("IPS_HostBasedSetupService", "AdminSetup", { "NetAdminPassEncryptionType": NetAdminPassEncryptionType, "NetworkAdminPassword": NetworkAdminPassword, "McNonce": McNonce, "SigningAlgorithm": SigningAlgorithm, "DigitalSignature": DigitalSignature }, callback_func); }
+ obj.IPS_HostBasedSetupService_UpgradeClientToAdmin = function (McNonce, SigningAlgorithm, DigitalSignature, callback_func) { obj.Exec("IPS_HostBasedSetupService", "UpgradeClientToAdmin", { "McNonce": McNonce, "SigningAlgorithm": SigningAlgorithm, "DigitalSignature": DigitalSignature }, callback_func); }
+ obj.IPS_HostBasedSetupService_DisableClientControlMode = function (_method_dummy, callback_func) { obj.Exec("IPS_HostBasedSetupService", "DisableClientControlMode", { "_method_dummy": _method_dummy }, callback_func); }
+ obj.IPS_KVMRedirectionSettingData_TerminateSession = function (callback_func) { obj.Exec("IPS_KVMRedirectionSettingData", "TerminateSession", {}, callback_func); }
+ obj.IPS_KVMRedirectionSettingData_DataChannelRead = function (callback_func) { obj.Exec("IPS_KVMRedirectionSettingData", "DataChannelRead", {}, callback_func); }
+ obj.IPS_KVMRedirectionSettingData_DataChannelWrite = function (Data, callback_func) { obj.Exec("IPS_KVMRedirectionSettingData", "DataChannelWrite", { "DataMessage": Data }, callback_func); }
+ obj.IPS_OptInService_StartOptIn = function (callback_func) { obj.Exec("IPS_OptInService", "StartOptIn", {}, callback_func); }
+ obj.IPS_OptInService_CancelOptIn = function (callback_func) { obj.Exec("IPS_OptInService", "CancelOptIn", {}, callback_func); }
+ obj.IPS_OptInService_SendOptInCode = function (OptInCode, callback_func) { obj.Exec("IPS_OptInService", "SendOptInCode", { "OptInCode": OptInCode }, callback_func); }
+ obj.IPS_OptInService_StartService = function (callback_func) { obj.Exec("IPS_OptInService", "StartService", {}, callback_func); }
+ obj.IPS_OptInService_StopService = function (callback_func) { obj.Exec("IPS_OptInService", "StopService", {}, callback_func); }
+ obj.IPS_OptInService_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("IPS_OptInService", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
+ obj.IPS_PowerManagementService_RequestOSPowerSavingStateChange = function (PowerState, ManagedElement, Time, TimeoutPeriod, callback_func) { obj.Exec("IPS_PowerManagementService", "RequestOSPowerSavingStateChange", { "OSPowerSavingState": PowerState, "ManagedElement": ManagedElement, "Time": Time, "TimeoutPeriod": TimeoutPeriod }, callback_func, 0, 1); }
+ obj.IPS_ProvisioningRecordLog_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("IPS_ProvisioningRecordLog", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
+ obj.IPS_ProvisioningRecordLog_ClearLog = function (_method_dummy, callback_func) { obj.Exec("IPS_ProvisioningRecordLog", "ClearLog", { "_method_dummy": _method_dummy }, callback_func); }
+ obj.IPS_ScreenConfigurationService_SetSessionState = function (SessionState, ConsecutiveRebootsNum, callback_func) { obj.Exec("IPS_ScreenConfigurationService", "SetSessionState", { "SessionState": SessionState, "ConsecutiveRebootsNum": ConsecutiveRebootsNum }, callback_func); }
+ obj.IPS_SecIOService_RequestStateChange = function (RequestedState, TimeoutPeriod, callback_func) { obj.Exec("IPS_SecIOService", "RequestStateChange", { "RequestedState": RequestedState, "TimeoutPeriod": TimeoutPeriod }, callback_func); }
+ obj.IPS_HTTPProxyService_AddProxyAccessPoint = function (AccessInfo, InfoFormat, Port, NetworkDnsSuffix, callback_func) { obj.Exec("IPS_HTTPProxyService", "AddProxyAccessPoint", { "AccessInfo": AccessInfo, "InfoFormat": InfoFormat, "Port": Port, "NetworkDnsSuffix": NetworkDnsSuffix }, callback_func); }
+
+ obj.AmtStatusToStr = function (code) { if (obj.AmtStatusCodes[code]) return obj.AmtStatusCodes[code]; else return "UNKNOWN_ERROR" }
+ obj.AmtStatusCodes = {
+ 0x0000: "SUCCESS",
+ 0x0001: "INTERNAL_ERROR",
+ 0x0002: "NOT_READY",
+ 0x0003: "INVALID_PT_MODE",
+ 0x0004: "INVALID_MESSAGE_LENGTH",
+ 0x0005: "TABLE_FINGERPRINT_NOT_AVAILABLE",
+ 0x0006: "INTEGRITY_CHECK_FAILED",
+ 0x0007: "UNSUPPORTED_ISVS_VERSION",
+ 0x0008: "APPLICATION_NOT_REGISTERED",
+ 0x0009: "INVALID_REGISTRATION_DATA",
+ 0x000A: "APPLICATION_DOES_NOT_EXIST",
+ 0x000B: "NOT_ENOUGH_STORAGE",
+ 0x000C: "INVALID_NAME",
+ 0x000D: "BLOCK_DOES_NOT_EXIST",
+ 0x000E: "INVALID_BYTE_OFFSET",
+ 0x000F: "INVALID_BYTE_COUNT",
+ 0x0010: "NOT_PERMITTED",
+ 0x0011: "NOT_OWNER",
+ 0x0012: "BLOCK_LOCKED_BY_OTHER",
+ 0x0013: "BLOCK_NOT_LOCKED",
+ 0x0014: "INVALID_GROUP_PERMISSIONS",
+ 0x0015: "GROUP_DOES_NOT_EXIST",
+ 0x0016: "INVALID_MEMBER_COUNT",
+ 0x0017: "MAX_LIMIT_REACHED",
+ 0x0018: "INVALID_AUTH_TYPE",
+ 0x0019: "AUTHENTICATION_FAILED",
+ 0x001A: "INVALID_DHCP_MODE",
+ 0x001B: "INVALID_IP_ADDRESS",
+ 0x001C: "INVALID_DOMAIN_NAME",
+ 0x001D: "UNSUPPORTED_VERSION",
+ 0x001E: "REQUEST_UNEXPECTED",
+ 0x001F: "INVALID_TABLE_TYPE",
+ 0x0020: "INVALID_PROVISIONING_STATE",
+ 0x0021: "UNSUPPORTED_OBJECT",
+ 0x0022: "INVALID_TIME",
+ 0x0023: "INVALID_INDEX",
+ 0x0024: "INVALID_PARAMETER",
+ 0x0025: "INVALID_NETMASK",
+ 0x0026: "FLASH_WRITE_LIMIT_EXCEEDED",
+ 0x0027: "INVALID_IMAGE_LENGTH",
+ 0x0028: "INVALID_IMAGE_SIGNATURE",
+ 0x0029: "PROPOSE_ANOTHER_VERSION",
+ 0x002A: "INVALID_PID_FORMAT",
+ 0x002B: "INVALID_PPS_FORMAT",
+ 0x002C: "BIST_COMMAND_BLOCKED",
+ 0x002D: "CONNECTION_FAILED",
+ 0x002E: "CONNECTION_TOO_MANY",
+ 0x002F: "RNG_GENERATION_IN_PROGRESS",
+ 0x0030: "RNG_NOT_READY",
+ 0x0031: "CERTIFICATE_NOT_READY",
+ 0x0400: "DISABLED_BY_POLICY",
+ 0x0800: "NETWORK_IF_ERROR_BASE",
+ 0x0801: "UNSUPPORTED_OEM_NUMBER",
+ 0x0802: "UNSUPPORTED_BOOT_OPTION",
+ 0x0803: "INVALID_COMMAND",
+ 0x0804: "INVALID_SPECIAL_COMMAND",
+ 0x0805: "INVALID_HANDLE",
+ 0x0806: "INVALID_PASSWORD",
+ 0x0807: "INVALID_REALM",
+ 0x0808: "STORAGE_ACL_ENTRY_IN_USE",
+ 0x0809: "DATA_MISSING",
+ 0x080A: "DUPLICATE",
+ 0x080B: "EVENTLOG_FROZEN",
+ 0x080C: "PKI_MISSING_KEYS",
+ 0x080D: "PKI_GENERATING_KEYS",
+ 0x080E: "INVALID_KEY",
+ 0x080F: "INVALID_CERT",
+ 0x0810: "CERT_KEY_NOT_MATCH",
+ 0x0811: "MAX_KERB_DOMAIN_REACHED",
+ 0x0812: "UNSUPPORTED",
+ 0x0813: "INVALID_PRIORITY",
+ 0x0814: "NOT_FOUND",
+ 0x0815: "INVALID_CREDENTIALS",
+ 0x0816: "INVALID_PASSPHRASE",
+ 0x0818: "NO_ASSOCIATION",
+ 0x081B: "AUDIT_FAIL",
+ 0x081C: "BLOCKING_COMPONENT",
+ 0x0821: "USER_CONSENT_REQUIRED",
+ 0x1000: "APP_INTERNAL_ERROR",
+ 0x1001: "NOT_INITIALIZED",
+ 0x1002: "LIB_VERSION_UNSUPPORTED",
+ 0x1003: "INVALID_PARAM",
+ 0x1004: "RESOURCES",
+ 0x1005: "HARDWARE_ACCESS_ERROR",
+ 0x1006: "REQUESTOR_NOT_REGISTERED",
+ 0x1007: "NETWORK_ERROR",
+ 0x1008: "PARAM_BUFFER_TOO_SHORT",
+ 0x1009: "COM_NOT_INITIALIZED_IN_THREAD",
+ 0x100A: "URL_REQUIRED"
+ }
+
+ //
+ // Methods used for getting the event log
+ //
+
+ obj.GetMessageLog = function (func, tag) {
+ obj.AMT_MessageLog_PositionToFirstRecord(_GetMessageLog0, [func, tag, []]);
+ }
+ function _GetMessageLog0(stack, name, responses, status, tag) {
+ if (status != 200 || responses.Body['ReturnValue'] != '0') { tag[0](obj, null, tag[2]); return; }
+ obj.AMT_MessageLog_GetRecords(responses.Body["IterationIdentifier"], 390, _GetMessageLog1, tag);
+ }
+ function _GetMessageLog1(stack, name, responses, status, tag) {
+ if (status != 200 || responses.Body['ReturnValue'] != '0') { tag[0](obj, null, tag[2]); return; }
+ var i, j, x, e, AmtMessages = tag[2], t = new Date(), TimeStamp, ra = responses.Body['RecordArray'];
+ if (typeof ra === 'string') { responses.Body['RecordArray'] = [responses.Body['RecordArray']]; }
+
+ for (i in ra) {
+ e = null;
+ try {
+ // ###BEGIN###{!Mode-MeshCentral2}
+ // NodeJS detection
+ var isNode = new Function('try {return this===global;}catch(e){return false;}');
+ if (isNode()) { e = require('atob')(ra[i]); } else { e = window.atob(ra[i]); }
+ // ###END###{!Mode-MeshCentral2}
+ // ###BEGIN###{Mode-MeshCentral2}
+ e = window.atob(ra[i]);
+ // ###END###{Mode-MeshCentral2}
+ } catch (ex) { }
+ if (e != null) {
+ TimeStamp = ReadIntX(e, 0);
+ if ((TimeStamp > 0) && (TimeStamp < 0xFFFFFFFF)) {
+ x = { 'DeviceAddress': e.charCodeAt(4), 'EventSensorType': e.charCodeAt(5), 'EventType': e.charCodeAt(6), 'EventOffset': e.charCodeAt(7), 'EventSourceType': e.charCodeAt(8), 'EventSeverity': e.charCodeAt(9), 'SensorNumber': e.charCodeAt(10), 'Entity': e.charCodeAt(11), 'EntityInstance': e.charCodeAt(12), 'EventData': [], 'Time': new Date((TimeStamp + (t.getTimezoneOffset() * 60)) * 1000) };
+ for (j = 13; j < 21; j++) { x['EventData'].push(e.charCodeAt(j)); }
+ x['EntityStr'] = _SystemEntityTypes[x['Entity']];
+ x['Desc'] = _GetEventDetailStr(x['EventSensorType'], x['EventOffset'], x['EventData'], x['Entity']);
+ if (!x['EntityStr']) x['EntityStr'] = "Unknown";
+ AmtMessages.push(x);
+ }
+ }
+ }
+
+ if (responses.Body["NoMoreRecords"] != true) { obj.AMT_MessageLog_GetRecords(responses.Body["IterationIdentifier"], 390, _GetMessageLog1, [tag[0], AmtMessages, tag[2]]); } else { tag[0](obj, AmtMessages, tag[2]); }
+ }
+
+ var _EventTrapSourceTypes = "Platform firmware (e.g. BIOS)|SMI handler|ISV system management software|Alert ASIC|IPMI|BIOS vendor|System board set vendor|System integrator|Third party add-in|OSV|NIC|System management card".split('|');
+ var _SystemFirmwareError = "Unspecified.|No system memory is physically installed in the system.|No usable system memory, all installed memory has experienced an unrecoverable failure.|Unrecoverable hard-disk/ATAPI/IDE device failure.|Unrecoverable system-board failure.|Unrecoverable diskette subsystem failure.|Unrecoverable hard-disk controller failure.|Unrecoverable PS/2 or USB keyboard failure.|Removable boot media not found.|Unrecoverable video controller failure.|No video device detected.|Firmware (BIOS) ROM corruption detected.|CPU voltage mismatch (processors that share same supply have mismatched voltage requirements)|CPU speed matching failure".split('|');
+ var _SystemFirmwareProgress = "Unspecified.|Memory initialization.|Starting hard-disk initialization and test|Secondary processor(s) initialization|User authentication|User-initiated system setup|USB resource configuration|PCI resource configuration|Option ROM initialization|Video initialization|Cache initialization|SM Bus initialization|Keyboard controller initialization|Embedded controller/management controller initialization|Docking station attachment|Enabling docking station|Docking station ejection|Disabling docking station|Calling operating system wake-up vector|Starting operating system boot process|Baseboard or motherboard initialization|reserved|Floppy initialization|Keyboard test|Pointing device test|Primary processor initialization".split('|');
+ var _SystemEntityTypes = "Unspecified|Other|Unknown|Processor|Disk|Peripheral|System management module|System board|Memory module|Processor module|Power supply|Add in card|Front panel board|Back panel board|Power system board|Drive backplane|System internal expansion board|Other system board|Processor board|Power unit|Power module|Power management board|Chassis back panel board|System chassis|Sub chassis|Other chassis board|Disk drive bay|Peripheral bay|Device bay|Fan cooling|Cooling unit|Cable interconnect|Memory device|System management software|BIOS|Intel(r) ME|System bus|Group|Intel(r) ME|External environment|Battery|Processing blade|Connectivity switch|Processor/memory module|I/O module|Processor I/O module|Management controller firmware|IPMI channel|PCI bus|PCI express bus|SCSI bus|SATA/SAS bus|Processor front side bus".split('|');
+ obj.RealmNames = "||Redirection||Hardware Asset|Remote Control|Storage|Event Manager|Storage Admin|Agent Presence Local|Agent Presence Remote|Circuit Breaker|Network Time|General Information|Firmware Update|EIT|LocalUN|Endpoint Access Control|Endpoint Access Control Admin|Event Log Reader|Audit Log|ACL Realm|||Local System".split('|');
+ obj.WatchdogCurrentStates = { 1: 'Not Started', 2: 'Stopped', 4: 'Running', 8: 'Expired', 16: 'Suspended' };
+
+ function _GetEventDetailStr(eventSensorType, eventOffset, eventDataField, entity) {
+
+ if (eventSensorType == 15) {
+ if (eventDataField[0] == 235) return "Invalid Data";
+ if (eventOffset == 0) return _SystemFirmwareError[eventDataField[1]];
+ return _SystemFirmwareProgress[eventDataField[1]];
+ }
+
+ if ((eventSensorType == 18) && (eventDataField[0] == 170)) { // System watchdog event
+ return "Agent watchdog " + char2hex(eventDataField[4]) + char2hex(eventDataField[3]) + char2hex(eventDataField[2]) + char2hex(eventDataField[1]) + "-" + char2hex(eventDataField[6]) + char2hex(eventDataField[5]) + "-... changed to " + obj.WatchdogCurrentStates[eventDataField[7]];
+ }
+
+ if ((eventSensorType == 5) && (eventOffset == 0)) { // System chassis
+ return "Case intrusion";
+ }
+
+ if ((eventSensorType == 192) && (eventOffset == 0) && (eventDataField[0] == 170) && (eventDataField[1] == 48))
+ {
+ if (eventDataField[2] == 0) return "A remote Serial Over LAN session was established.";
+ if (eventDataField[2] == 1) return "Remote Serial Over LAN session finished. User control was restored.";
+ if (eventDataField[2] == 2) return "A remote IDE-Redirection session was established.";
+ if (eventDataField[2] == 3) return "Remote IDE-Redirection session finished. User control was restored.";
+ }
+
+ if (eventSensorType == 36) {
+ var handle = (eventDataField[1] << 24) + (eventDataField[2] << 16) + (eventDataField[3] << 8) + eventDataField[4];
+ var nic = "#" + eventDataField[0];
+ if (eventDataField[0] == 0xAA) nic = "wired"; // TODO: Add wireless *****
+ //if (eventDataField[0] == 0xAA) nic = "wireless";
+
+ if (handle == 4294967293) { return "All received packet filter was matched on " + nic + " interface."; }
+ if (handle == 4294967292) { return "All outbound packet filter was matched on " + nic + " interface."; }
+ if (handle == 4294967290) { return "Spoofed packet filter was matched on " + nic + " interface."; }
+ return "Filter " + handle + " was matched on " + nic + " interface.";
+ }
+
+ if (eventSensorType == 192) {
+ if (eventDataField[2] == 0) return "Security policy invoked. Some or all network traffic (TX) was stopped.";
+ if (eventDataField[2] == 2) return "Security policy invoked. Some or all network traffic (RX) was stopped.";
+ return "Security policy invoked.";
+ }
+
+ if (eventSensorType == 193) {
+ if ((eventDataField[0] == 0xAA) && (eventDataField[1] == 0x30) && (eventDataField[2] == 0x00) && (eventDataField[3] == 0x00)) { return "User request for remote connection."; }
+ if ((eventDataField[0] == 0xAA) && (eventDataField[1] == 0x20) && (eventDataField[2] == 0x03) && (eventDataField[3] == 0x01)) { return "EAC error: attempt to get posture while NAC in Intel® AMT is disabled."; } // eventDataField = 0xAA20030100000000
+ if ((eventDataField[0] == 0xAA) && (eventDataField[1] == 0x20) && (eventDataField[2] == 0x04) && (eventDataField[3] == 0x00)) { return "HWA Error: general error"; } // Used to be "Certificate revoked." but don't know the source of this.
+ }
+
+ if (eventSensorType == 6) return "Authentication failed " + (eventDataField[1] + (eventDataField[2] << 8)) + " times. The system may be under attack.";
+ if (eventSensorType == 30) return "No bootable media";
+ if (eventSensorType == 32) return "Operating system lockup or power interrupt";
+ if (eventSensorType == 35) return "System boot failure";
+ if (eventSensorType == 37) return "System firmware started (at least one CPU is properly executing).";
+ return "Unknown Sensor Type #" + eventSensorType;
+ }
+
+// ###BEGIN###{AuditLog}
+
+ // Useful link: https://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide/default.htm?turl=WordDocuments%2Fsecurityadminevents.htm
+
+ var _AmtAuditStringTable =
+ {
+ 16: 'Security Admin',
+ 17: 'RCO',
+ 18: 'Redirection Manager',
+ 19: 'Firmware Update Manager',
+ 20: 'Security Audit Log',
+ 21: 'Network Time',
+ 22: 'Network Administration',
+ 23: 'Storage Administration',
+ 24: 'Event Manager',
+ 25: 'Circuit Breaker Manager',
+ 26: 'Agent Presence Manager',
+ 27: 'Wireless Configuration',
+ 28: 'EAC',
+ 29: 'KVM',
+ 30: 'User Opt-In Events',
+ 32: 'Screen Blanking',
+ 33: 'Watchdog Events',
+ 1600: 'Provisioning Started',
+ 1601: 'Provisioning Completed',
+ 1602: 'ACL Entry Added',
+ 1603: 'ACL Entry Modified',
+ 1604: 'ACL Entry Removed',
+ 1605: 'ACL Access with Invalid Credentials',
+ 1606: 'ACL Entry State',
+ 1607: 'TLS State Changed',
+ 1608: 'TLS Server Certificate Set',
+ 1609: 'TLS Server Certificate Remove',
+ 1610: 'TLS Trusted Root Certificate Added',
+ 1611: 'TLS Trusted Root Certificate Removed',
+ 1612: 'TLS Preshared Key Set',
+ 1613: 'Kerberos Settings Modified',
+ 1614: 'Kerberos Master Key Modified',
+ 1615: 'Flash Wear out Counters Reset',
+ 1616: 'Power Package Modified',
+ 1617: 'Set Realm Authentication Mode',
+ 1618: 'Upgrade Client to Admin Control Mode',
+ 1619: 'Unprovisioning Started',
+ 1700: 'Performed Power Up',
+ 1701: 'Performed Power Down',
+ 1702: 'Performed Power Cycle',
+ 1703: 'Performed Reset',
+ 1704: 'Set Boot Options',
+ 1800: 'IDER Session Opened',
+ 1801: 'IDER Session Closed',
+ 1802: 'IDER Enabled',
+ 1803: 'IDER Disabled',
+ 1804: 'SoL Session Opened',
+ 1805: 'SoL Session Closed',
+ 1806: 'SoL Enabled',
+ 1807: 'SoL Disabled',
+ 1808: 'KVM Session Started',
+ 1809: 'KVM Session Ended',
+ 1810: 'KVM Enabled',
+ 1811: 'KVM Disabled',
+ 1812: 'VNC Password Failed 3 Times',
+ 1900: 'Firmware Updated',
+ 1901: 'Firmware Update Failed',
+ 2000: 'Security Audit Log Cleared',
+ 2001: 'Security Audit Policy Modified',
+ 2002: 'Security Audit Log Disabled',
+ 2003: 'Security Audit Log Enabled',
+ 2004: 'Security Audit Log Exported',
+ 2005: 'Security Audit Log Recovered',
+ 2100: 'Intel® ME Time Set',
+ 2200: 'TCPIP Parameters Set',
+ 2201: 'Host Name Set',
+ 2202: 'Domain Name Set',
+ 2203: 'VLAN Parameters Set',
+ 2204: 'Link Policy Set',
+ 2205: 'IPv6 Parameters Set',
+ 2300: 'Global Storage Attributes Set',
+ 2301: 'Storage EACL Modified',
+ 2302: 'Storage FPACL Modified',
+ 2303: 'Storage Write Operation',
+ 2400: 'Alert Subscribed',
+ 2401: 'Alert Unsubscribed',
+ 2402: 'Event Log Cleared',
+ 2403: 'Event Log Frozen',
+ 2500: 'CB Filter Added',
+ 2501: 'CB Filter Removed',
+ 2502: 'CB Policy Added',
+ 2503: 'CB Policy Removed',
+ 2504: 'CB Default Policy Set',
+ 2505: 'CB Heuristics Option Set',
+ 2506: 'CB Heuristics State Cleared',
+ 2600: 'Agent Watchdog Added',
+ 2601: 'Agent Watchdog Removed',
+ 2602: 'Agent Watchdog Action Set',
+ 2700: 'Wireless Profile Added',
+ 2701: 'Wireless Profile Removed',
+ 2702: 'Wireless Profile Updated',
+ 2800: 'EAC Posture Signer SET',
+ 2801: 'EAC Enabled',
+ 2802: 'EAC Disabled',
+ 2803: 'EAC Posture State',
+ 2804: 'EAC Set Options',
+ 2900: 'KVM Opt-in Enabled',
+ 2901: 'KVM Opt-in Disabled',
+ 2902: 'KVM Password Changed',
+ 2903: 'KVM Consent Succeeded',
+ 2904: 'KVM Consent Failed',
+ 3000: 'Opt-In Policy Change',
+ 3001: 'Send Consent Code Event',
+ 3002: 'Start Opt-In Blocked Event'
+ }
+
+ // Return human readable extended audit log data
+ // TODO: Just put some of them here, but many more still need to be added, helpful link here:
+ // https://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide/default.htm?turl=WordDocuments%2Fsecurityadminevents.htm
+ obj.GetAuditLogExtendedDataStr = function (id, data) {
+ if ((id == 1602 || id == 1604) && data.charCodeAt(0) == 0) { return data.substring(2, 2 + data.charCodeAt(1)); } // ACL Entry Added/Removed (Digest)
+ if (id == 1603) { if (data.charCodeAt(1) == 0) { return data.substring(3); } return null; } // ACL Entry Modified
+ if (id == 1605) { return ["Invalid ME access", "Invalid MEBx access"][data.charCodeAt(0)]; } // ACL Access with Invalid Credentials
+ if (id == 1606) { var r = ["Disabled", "Enabled"][data.charCodeAt(0)]; if (data.charCodeAt(1) == 0) { r += ", " + data.substring(3); } return r;} // ACL Entry State
+ if (id == 1607) { return "Remote " + ["NoAuth", "ServerAuth", "MutualAuth"][data.charCodeAt(0)] + ", Local " + ["NoAuth", "ServerAuth", "MutualAuth"][data.charCodeAt(1)]; } // TLS State Changed
+ if (id == 1617) { return obj.RealmNames[ReadInt(data, 0)] + ", " + ["NoAuth", "Auth", "Disabled"][data.charCodeAt(4)]; } // Set Realm Authentication Mode
+ if (id == 1619) { return ["BIOS", "MEBx", "Local MEI", "Local WSMAN", "Remote WSAMN"][data.charCodeAt(0)]; } // Intel AMT Unprovisioning Started
+ if (id == 1900) { return "From " + ReadShort(data, 0) + "." + ReadShort(data, 2) + "." + ReadShort(data, 4) + "." + ReadShort(data, 6) + " to " + ReadShort(data, 8) + "." + ReadShort(data, 10) + "." + ReadShort(data, 12) + "." + ReadShort(data, 14); } // Firmware Updated
+ if (id == 2100) { var t4 = new Date(); t4.setTime(ReadInt(data, 0) * 1000 + (new Date().getTimezoneOffset() * 60000)); return t4.toLocaleString(); } // Intel AMT Time Set
+ if (id == 3000) { return "From " + ["None", "KVM", "All"][data.charCodeAt(0)] + " to " + ["None", "KVM", "All"][data.charCodeAt(1)]; } // Opt-In Policy Change
+ if (id == 3001) { return ["Success", "Failed 3 times"][data.charCodeAt(0)]; } // Send Consent Code Event
+ return null;
+ }
+
+ obj.GetAuditLog = function (func) {
+ obj.AMT_AuditLog_ReadRecords(1, _GetAuditLog0, [func, []]);
+ }
+
+ function _GetAuditLog0(stack, name, responses, status, tag) {
+ if (status != 200) { tag[0](obj, [], status); return; }
+ var ptr, i, e, x, r = tag[1], t = new Date(), TimeStamp;
+
+ if (responses.Body['RecordsReturned'] > 0) {
+ responses.Body['EventRecords'] = MakeToArray(responses.Body['EventRecords']);
+
+ for (i in responses.Body['EventRecords']) {
+ e = null;
+ try {
+ e = window.atob(responses.Body['EventRecords'][i]);
+ } catch (e) {
+ console.log(e + " " + responses.Body['EventRecords'][i])
+ }
+ x = { 'AuditAppID': ReadShort(e, 0), 'EventID': ReadShort(e, 2), 'InitiatorType': e.charCodeAt(4) };
+ x['AuditApp'] = _AmtAuditStringTable[x['AuditAppID']];
+ x['Event'] = _AmtAuditStringTable[(x['AuditAppID'] * 100) + x['EventID']];
+ if (!x['Event']) x['Event'] = '#' + x['EventID'];
+
+ // Read and process the initiator
+ if (x['InitiatorType'] == 0) {
+ // HTTP digest
+ var userlen = e.charCodeAt(5);
+ x['Initiator'] = e.substring(6, 6 + userlen);
+ ptr = 6 + userlen;
+ }
+ if (x['InitiatorType'] == 1) {
+ // Kerberos
+ x['KerberosUserInDomain'] = ReadInt(e, 5);
+ var userlen = e.charCodeAt(9);
+ x['Initiator'] = GetSidString(e.substring(10, 10 + userlen));
+ ptr = 10 + userlen;
+ }
+ if (x['InitiatorType'] == 2) {
+ // Local
+ x['Initiator'] = 'Local ';
+ ptr = 5;
+ }
+ if (x['InitiatorType'] == 3) {
+ // KVM Default Port
+ x['Initiator'] = 'KVM Default Port ';
+ ptr = 5;
+ }
+
+ // Read timestamp
+ TimeStamp = ReadInt(e, ptr);
+ x['Time'] = new Date((TimeStamp + (t.getTimezoneOffset() * 60)) * 1000);
+ ptr += 4;
+
+ // Read network access
+ x['MCLocationType'] = e.charCodeAt(ptr++);
+ var netlen = e.charCodeAt(ptr++);
+ x['NetAddress'] = e.substring(ptr, ptr + netlen);
+
+ // Read extended data
+ ptr += netlen;
+ var exlen = e.charCodeAt(ptr++);
+ x['Ex'] = e.substring(ptr, ptr + exlen);
+ x['ExStr'] = obj.GetAuditLogExtendedDataStr((x['AuditAppID'] * 100) + x['EventID'], x['Ex']);
+
+ r.push(x);
+ }
+ }
+ if (responses.Body['TotalRecordCount'] > r.length) {
+ obj.AMT_AuditLog_ReadRecords(r.length + 1, _GetAuditLog0, [tag[0], r]);
+ } else {
+ tag[0](obj, r, status);
+ }
+ }
+
+ // ###END###{AuditLog}
+
+ return obj;
+}
+
+
+// ###BEGIN###{Certificates}
+
+// Forge MD5
+function hex_md5(str) { if (str == null) { str = ''; } return forge.md.md5.create().update(str).digest().toHex(); }
+
+// ###END###{Certificates}
+
+// ###BEGIN###{!Certificates}
+
+// TinyMD5 from https://github.com/jbt/js-crypto
+
+// Perform MD5 setup
+var md5_k = [];
+for (var i = 0; i < 64;) { md5_k[i] = 0 | (Math.abs(Math.sin(++i)) * 4294967296); }
+
+// Perform MD5 on raw string and return hex
+function hex_md5(str) {
+ if (str == null) { str = ''; }
+ var b, c, d, j,
+ x = [],
+ str2 = unescape(encodeURI(str)),
+ a = str2.length,
+ h = [b = 1732584193, c = -271733879, ~b, ~c],
+ i = 0;
+
+ for (; i <= a;) x[i >> 2] |= (str2.charCodeAt(i) || 128) << 8 * (i++ % 4);
+
+ x[str = (a + 8 >> 6) * 16 + 14] = a * 8;
+ i = 0;
+
+ for (; i < str; i += 16) {
+ a = h; j = 0;
+ for (; j < 64;) {
+ a = [
+ d = a[3],
+ ((b = a[1] | 0) +
+ ((d = (
+ (a[0] +
+ [
+ b & (c = a[2]) | ~b & d,
+ d & b | ~d & c,
+ b ^ c ^ d,
+ c ^ (b | ~d)
+ ][a = j >> 4]
+ ) +
+ (md5_k[j] +
+ (x[[
+ j,
+ 5 * j + 1,
+ 3 * j + 5,
+ 7 * j
+ ][a] % 16 + i] | 0)
+ )
+ )) << (a = [
+ 7, 12, 17, 22,
+ 5, 9, 14, 20,
+ 4, 11, 16, 23,
+ 6, 10, 15, 21
+ ][4 * a + j++ % 4]) | d >>> 32 - a)
+ ),
+ b,
+ c
+ ];
+ }
+ for (j = 4; j;) h[--j] = h[j] + a[j];
+ }
+
+ str = '';
+ for (; j < 32;) str += ((h[j >> 3] >> ((1 ^ j++ & 7) * 4)) & 15).toString(16);
+ return str;
+}
+
+// ###END###{!Certificates}
+
+// Perform MD5 on raw string and return raw string result
+function rstr_md5(str) { return hex2rstr(hex_md5(str)); }
+
+/*
+Convert arguments into selector set and body XML. Used by AMT_WiFiPortConfigurationService_UpdateWiFiSettings.
+args = {
+ "WiFiEndpoint": {
+ __parameterType: 'reference',
+ __resourceUri: 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_WiFiEndpoint',
+ Name: 'WiFi Endpoint 0'
+ },
+ "WiFiEndpointSettingsInput":
+ {
+ __parameterType: 'instance',
+ __namespace: 'http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_WiFiEndpointSettings',
+ ElementName: document.querySelector('#editProfile-profileName').value,
+ InstanceID: 'Intel(r) AMT:WiFi Endpoint Settings ' + document.querySelector('#editProfile-profileName').value,
+ AuthenticationMethod: document.querySelector('#editProfile-networkAuthentication').value,
+ //BSSType: 3, // Intel(r) AMT supports only infrastructure networks
+ EncryptionMethod: document.querySelector('#editProfile-encryption').value,
+ SSID: document.querySelector('#editProfile-networkName').value,
+ Priority: 100,
+ PSKPassPhrase: document.querySelector('#editProfile-passPhrase').value
+ },
+ "IEEE8021xSettingsInput": null,
+ "ClientCredential": null,
+ "CACredential": null
+},
+*/
+function execArgumentsToXml(args) {
+ if(args === undefined || args === null) return null;
+
+ var result = '';
+ for(var argName in args) {
+ var arg = args[argName];
+ if(!arg) continue;
+ if(arg['__parameterType'] === 'reference') result += referenceToXml(argName, arg);
+ else result += instanceToXml(argName, arg);
+ //if(arg['__isInstance']) result += instanceToXml(argName, arg);
+ }
+ return result;
+}
+
+/**
+ * Convert JavaScript object into XML
+
+
+ Wireless-Profile-Admin
+ Intel(r) AMT:WiFi Endpoint Settings Wireless-Profile-Admin
+ 6
+ 4
+ 100
+ xxxxxxxx
+
+ */
+function instanceToXml(instanceName, inInstance) {
+ if(inInstance === undefined || inInstance === null) return null;
+
+ var hasNamespace = !!inInstance['__namespace'];
+ var startTag = hasNamespace ? '';
+ for(var prop in inInstance) {
+ if (!inInstance.hasOwnProperty(prop) || prop.indexOf('__') === 0) continue;
+
+ if (typeof inInstance[prop] === 'function' || Array.isArray(inInstance[prop]) ) continue;
+
+ if (typeof inInstance[prop] === 'object') {
+ //result += startTag + prop +'>' + instanceToXml('prop', inInstance[prop]) + endTag + prop +'>';
+ console.error('only convert one level down...');
+ }
+ else {
+ result += startTag + prop +'>' + inInstance[prop].toString() + endTag + prop +'>';
+ }
+ }
+ result += '';
+ return result;
+}
+
+
+/**
+ * Convert a selector set into XML. Expect no nesting.
+ * {
+ * selectorName : selectorValue,
+ * selectorName : selectorValue,
+ * ... ...
+ * }
+
+
+ http://192.168.1.103:16992/wsman
+
+ http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_WiFiEndpoint
+
+ WiFi Endpoint 0
+
+
+
+
+ */
+function referenceToXml(referenceName, inReference) {
+ if(inReference === undefined || inReference === null ) return null;
+
+ var result = '/wsman '+ inReference['__resourceUri']+' ';
+ for(var selectorName in inReference) {
+ if (!inReference.hasOwnProperty(selectorName) || selectorName.indexOf('__') === 0) continue;
+
+ if (typeof inReference[selectorName] === 'function' ||
+ typeof inReference[selectorName] === 'object' ||
+ Array.isArray(inReference[selectorName]) )
+ continue;
+
+ result += '' + inReference[selectorName].toString() + ' ';
+ }
+
+ result += ' ';
+ return result;
+}
+
+// Convert a byte array of SID into string
+function GetSidString(sid) {
+ var r = "S-" + sid.charCodeAt(0) + "-" + sid.charCodeAt(7);
+ for (var i = 2; i < (sid.length / 4) ; i++) r += "-" + ReadIntX(sid, i * 4);
+ return r;
+}
+
+// Convert a SID readable string into bytes
+function GetSidByteArray(sidString) {
+ if (!sidString || sidString == null) return null;
+ var sidParts = sidString.split('-');
+
+ // Make sure the SID has at least 4 parts and starts with 'S'
+ if (sidParts.length < 4 || (sidParts[0] != 's' && sidParts[0] != 'S')) return null;
+
+ // Check that each part of the SID is really an integer
+ for (var i = 1; i < sidParts.length; i++) { var y = parseInt(sidParts[i]); if (y != sidParts[i]) return null; sidParts[i] = y; }
+
+ // Version (8 bit) + Id count (8 bit) + 48 bit in big endian -- DO NOT use bitwise right shift operator. JavaScript converts the number into a 32 bit integer before shifting. In real world, it's highly likely this part is always 0.
+ var r = String.fromCharCode(sidParts[1]) + String.fromCharCode(sidParts.length - 3) + ShortToStr(Math.floor(sidParts[2] / Math.pow(2, 32))) + IntToStr((sidParts[2]) & 0xFFFF);
+
+ // the rest are in 32 bit in little endian
+ for (var i = 3; i < sidParts.length; i++) r += IntToStrX(sidParts[i]);
+ return r;
+}
diff --git a/amt-certificates-0.0.1.js b/amt-certificates-0.0.1.js
new file mode 100644
index 0000000..b5b767d
--- /dev/null
+++ b/amt-certificates-0.0.1.js
@@ -0,0 +1,181 @@
+/**
+* @fileoverview Intel(r) AMT Certificate functions
+* @author Ylian Saint-Hilaire
+* @version v0.2.0b
+*/
+
+// Check which key pair matches the public key in the certificate
+function amtcert_linkCertPrivateKey(certs, keys) {
+ for (var i in certs) {
+ var cert = certs[i];
+ try {
+ if (xxCertPrivateKeys.length == 0) return;
+ var publicKeyPEM = forge.pki.publicKeyToPem(forge.pki.certificateFromAsn1(forge.asn1.fromDer(cert.X509Certificate)).publicKey).substring(28 + 32).replace(/(\r\n|\n|\r)/gm, "");
+ for (var j = 0; j < keys.length; j++) {
+ if (publicKeyPEM === (keys[j]['DERKey'] + '-----END PUBLIC KEY-----')) {
+ keys[j].XCert = cert; // Link the key pair to the certificate
+ cert.XPrivateKey = keys[j]; // Link the certificate to the key pair
+ }
+ }
+ } catch (e) { console.log(e); }
+ }
+}
+
+// Load a P12 file, decodes it using the password and returns the private key handle
+function amtcert_loadP12File(file, password, func) {
+ try {
+ // Encode in Base64 so Forge API can parse it.
+ var p12Der = window.forge.util.decode64(btoa(file));
+ var p12Asn1 = window.forge.asn1.fromDer(p12Der);
+ var p12 = window.forge.pkcs12.pkcs12FromAsn1(p12Asn1, password);
+
+ // Private key is stored in a shrouded key bag
+ var bags = p12.getBags({ bagType: window.forge.pki.oids.pkcs8ShroudedKeyBag });
+ console.assert(bags[window.forge.pki.oids.pkcs8ShroudedKeyBag] && bags[window.forge.pki.oids.pkcs8ShroudedKeyBag].length > 0);
+
+ // Import the Forge private key structure into Web Crypto
+ var privateKey = bags[window.forge.pki.oids.pkcs8ShroudedKeyBag][0].key;
+ var rsaPrivateKey = window.forge.pki.privateKeyToAsn1(privateKey);
+ var privateKeyInfo = window.forge.pki.wrapRsaPrivateKey(rsaPrivateKey);
+ var pkcs8 = window.forge.asn1.toDer(privateKeyInfo).getBytes();
+
+ // Get the issuer attributes
+ var certBags = p12.getBags({ bagType: window.forge.pki.oids.certBag });
+ var issuerAttributes = certBags[window.forge.pki.oids.certBag][0].cert.subject.attributes;
+
+ var bags1 = p12.getBags({ bagType: forge.pki.oids.certBag });
+ var cert = bags1[forge.pki.oids.certBag][0].cert;
+
+ func(privateKey, issuerAttributes, cert);
+ return true;
+ } catch (ex) { }
+ return false;
+}
+
+function amtcert_signWithCaKey(DERKey, caPrivateKey, certAttributes, issuerAttributes, extKeyUsage) {
+ if (!caPrivateKey || caPrivateKey == null) {
+ var certAndKey = amtcert_createCertificate(issuerAttributes);
+ caPrivateKey = certAndKey.key;
+ }
+ return amtcert_createCertificate(certAttributes, caPrivateKey, DERKey, issuerAttributes, extKeyUsage);
+}
+
+// --- Extended Key Usage OID's ---
+// 1.3.6.1.5.5.7.3.1 = TLS Server certificate
+// 1.3.6.1.5.5.7.3.2 = TLS Client certificate
+// 2.16.840.1.113741.1.2.1 = Intel AMT Remote Console
+// 2.16.840.1.113741.1.2.2 = Intel AMT Local Console
+// 2.16.840.1.113741.1.2.3 = Intel AMT Client Setup Certificate (Zero-Touch)
+
+// Generate a certificate with a set of attributes signed by a rootCert. If the rootCert is obmitted, the generated certificate is self-signed.
+function amtcert_createCertificate(certAttributes, caPrivateKey, DERKey, issuerAttributes, extKeyUsage) {
+ // Generate a keypair and create an X.509v3 certificate
+ var keys, cert = forge.pki.createCertificate();
+ if (!DERKey) {
+ keys = forge.pki.rsa.generateKeyPair(2048);
+ cert.publicKey = keys.publicKey;
+ } else {
+ cert.publicKey = forge.pki.publicKeyFromPem('-----BEGIN PUBLIC KEY-----' + DERKey + '-----END PUBLIC KEY-----');
+ }
+ cert.serialNumber = '' + Math.floor((Math.random() * 100000) + 1);
+ cert.validity.notBefore = new Date(2018, 0, 1);
+ //cert.validity.notBefore.setFullYear(cert.validity.notBefore.getFullYear() - 1); // Create a certificate that is valid one year before, to make sure out-of-sync clocks don't reject this cert.
+ cert.validity.notAfter = new Date(2049, 11, 31);
+ //cert.validity.notAfter.setFullYear(cert.validity.notAfter.getFullYear() + 20);
+ var attrs = [];
+ if (certAttributes['CN']) attrs.push({ name: 'commonName', value: certAttributes['CN'] });
+ if (certAttributes['C']) attrs.push({ name: 'countryName', value: certAttributes['C'] });
+ if (certAttributes['ST']) attrs.push({ shortName: 'ST', value: certAttributes['ST'] });
+ if (certAttributes['O']) attrs.push({ name: 'organizationName', value: certAttributes['O'] });
+ cert.setSubject(attrs);
+
+ if (caPrivateKey) {
+ // Use root attributes
+ var rootattrs = [];
+ if (issuerAttributes['CN']) rootattrs.push({ name: 'commonName', value: issuerAttributes['CN'] });
+ if (issuerAttributes['C']) rootattrs.push({ name: 'countryName', value: issuerAttributes['C'] });
+ if (issuerAttributes['ST']) rootattrs.push({ shortName: 'ST', value: issuerAttributes['ST'] });
+ if (issuerAttributes['O']) rootattrs.push({ name: 'organizationName', value: issuerAttributes['O'] });
+ cert.setIssuer(rootattrs);
+ } else {
+ // Use our own attributes
+ cert.setIssuer(attrs);
+ }
+
+ if (caPrivateKey == undefined) {
+ // Create a root certificate
+ cert.setExtensions([{
+ name: 'basicConstraints',
+ cA: true
+ }, {
+ name: 'nsCertType',
+ sslCA: true,
+ emailCA: true,
+ objCA: true
+ }, {
+ name: 'subjectKeyIdentifier'
+ }]);
+ } else {
+ if (extKeyUsage == null) { extKeyUsage = { name: 'extKeyUsage', serverAuth: true, } } else { extKeyUsage.name = 'extKeyUsage'; }
+
+ /*
+ {
+ name: 'extKeyUsage',
+ serverAuth: true,
+ clientAuth: true,
+ codeSigning: true,
+ emailProtection: true,
+ timeStamping: true,
+ '2.16.840.1.113741.1.2.1': true
+ }
+ */
+
+ // Create a leaf certificate
+ cert.setExtensions([{
+ name: 'basicConstraints'
+ }, {
+ name: 'keyUsage',
+ keyCertSign: true,
+ digitalSignature: true,
+ nonRepudiation: true,
+ keyEncipherment: true,
+ dataEncipherment: true
+ }, extKeyUsage, {
+ name: 'nsCertType',
+ client: true,
+ server: true,
+ email: true,
+ objsign: true,
+ }, {
+ name: 'subjectKeyIdentifier'
+ }]);
+ }
+
+ // Self-sign certificate
+ if (caPrivateKey) {
+ cert.sign(caPrivateKey, forge.md.sha256.create());
+ } else {
+ cert.sign(keys.privateKey, forge.md.sha256.create());
+ }
+
+ if (DERKey) {
+ return cert;
+ } else {
+ return { 'cert': cert, 'key': keys.privateKey };
+ }
+}
+
+function _stringToArrayBuffer(str) {
+ var buf = new ArrayBuffer(str.length);
+ var bufView = new Uint8Array(buf);
+ for (var i = 0, strLen = str.length; i < strLen; i++) { bufView[i] = str.charCodeAt(i); }
+ return buf;
+}
+
+function _arrayBufferToString(buffer) {
+ var binary = '';
+ var bytes = new Uint8Array(buffer);
+ var len = bytes.byteLength;
+ for (var i = 0; i < len; i++) { binary += String.fromCharCode(bytes[i]); }
+ return binary;
+}
diff --git a/amt-desktop-0.0.2.js b/amt-desktop-0.0.2.js
new file mode 100644
index 0000000..42aefa8
--- /dev/null
+++ b/amt-desktop-0.0.2.js
@@ -0,0 +1,923 @@
+/**
+* @description Remote Desktop
+* @author Ylian Saint-Hilaire
+* @version v0.0.2g
+*/
+
+// Construct a MeshServer object
+var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
+ var obj = {};
+ obj.canvasid = divid;
+ obj.scrolldiv = scrolldiv;
+ obj.canvas = Q(divid).getContext("2d");
+ obj.protocol = 2; // KVM
+ obj.state = 0;
+ obj.acc = "";
+ obj.ScreenWidth = 960;
+ obj.ScreenHeight = 700;
+ obj.width = 0;
+ obj.height = 0;
+ obj.rwidth = 0;
+ obj.rheight = 0;
+ obj.bpp = 2; // Bytes per pixel (1 or 2 supported)
+ obj.graymode = 0; // 0 = Color, 1 = 256 grays, 2 = 16 grays. obj.bbp must be 1 in gray modes.
+ obj.useZRLE = true;
+ obj.showmouse = true;
+ obj.buttonmask = 0;
+ //obj.inbytes = 0;
+ //obj.outbytes = 0;
+ obj.spare = null;
+ obj.sparew = 0;
+ obj.spareh = 0;
+ obj.sparew2 = 0;
+ obj.spareh2 = 0;
+ obj.sparecache = {};
+ obj.ZRLEfirst = 1;
+ obj.onScreenSizeChange = null;
+ obj.frameRateDelay = 0;
+ // ###BEGIN###{DesktopRotation}
+ obj.noMouseRotate = false;
+ obj.rotation = 0;
+ // ###END###{DesktopRotation}
+ // ###BEGIN###{DesktopInband}
+ obj.kvmDataSupported = false;
+ obj.onKvmData = null;
+ obj.onKvmDataPending = [];
+ obj.onKvmDataAck = -1;
+ obj.holding = false;
+ obj.lastKeepAlive = Date.now();
+ // ###END###{DesktopInband}
+
+ obj.mNagleTimer = null; // Mouse motion slowdown timer
+ obj.mx = 0; // Last mouse x position
+ obj.my = 0; // Last mouse y position
+ // ###BEGIN###{DesktopFocus}
+ obj.ox = -1; // Old mouse x position
+ obj.oy = -1; // Old mouse y position
+ obj.focusmode = 0;
+ // ###END###{DesktopFocus}
+ // ###BEGIN###{Inflate}
+ obj.inflate = ZLIB.inflateInit(-15);
+ // ###END###{Inflate}
+
+ // Private method
+ obj.Debug = function (msg) { console.log(msg); }
+
+ obj.xxStateChange = function (newstate) {
+ if (newstate == 0) {
+ obj.canvas.fillStyle = '#000000';
+ obj.canvas.fillRect(0, 0, obj.width, obj.height);
+ obj.canvas.canvas.width = obj.rwidth = obj.width = 640;
+ obj.canvas.canvas.height = obj.rheight = obj.height = 400;
+ QS(obj.canvasid).cursor = 'auto';
+ // ###BEGIN###{Inflate}
+ obj.inflate = ZLIB.inflateInit(-15); // Reset inflate
+ // ###END###{Inflate}
+ } else {
+ if (!obj.showmouse) { QS(obj.canvasid).cursor = 'none'; }
+ }
+ }
+
+ obj.ProcessData = function (data) {
+ if (!data) return;
+ // obj.Debug("KRecv(" + data.length + "): " + rstr2hex(data));
+ //obj.inbytes += data.length;
+ //obj.Debug("KRecv(" + obj.inbytes + ")");
+ obj.acc += data;
+ while (obj.acc.length > 0) {
+ //obj.Debug("KAcc(" + obj.acc.length + "): " + rstr2hex(obj.acc));
+ var cmdsize = 0;
+ if (obj.state == 0 && obj.acc.length >= 12) {
+ // Getting handshake & version
+ cmdsize = 12;
+ //if (obj.acc.substring(0, 4) != "RFB ") { return obj.Stop(); }
+ //var version = parseFloat(obj.acc.substring(4, 11));
+ //obj.Debug("KVersion: " + version);
+ obj.state = 1;
+ obj.Send("RFB 003.008\n");
+ }
+ else if (obj.state == 1 && obj.acc.length >= 1) {
+ // Getting security options
+ cmdsize = obj.acc.charCodeAt(0) + 1;
+ obj.Send(String.fromCharCode(1)); // Send the "None" security type. Since we already authenticated using redirection digest auth, we don't need to do this again.
+ obj.state = 2;
+ }
+ else if (obj.state == 2 && obj.acc.length >= 4) {
+ // Getting security response
+ cmdsize = 4;
+ if (ReadInt(obj.acc, 0) != 0) { return obj.Stop(); }
+ obj.Send(String.fromCharCode(1)); // Send share desktop flag
+ obj.state = 3;
+ }
+ else if (obj.state == 3 && obj.acc.length >= 24) {
+ // Getting server init
+ // ###BEGIN###{DesktopRotation}
+ obj.rotation = 0; // We don't currently support screen init while rotated.
+ // ###END###{DesktopRotation}
+ var namelen = ReadInt(obj.acc, 20);
+ if (obj.acc.length < 24 + namelen) return;
+ cmdsize = 24 + namelen;
+ obj.canvas.canvas.width = obj.rwidth = obj.width = obj.ScreenWidth = ReadShort(obj.acc, 0);
+ obj.canvas.canvas.height = obj.rheight = obj.height = obj.ScreenHeight = ReadShort(obj.acc, 2);
+
+ // These are all values we don't really need, we are going to only run in RGB565 or RGB332 and not use the flexibility provided by these settings.
+ // Makes the javascript code smaller and maybe a bit faster.
+ /*
+ obj.xbpp = obj.acc.charCodeAt(4);
+ obj.depth = obj.acc.charCodeAt(5);
+ obj.bigend = obj.acc.charCodeAt(6);
+ obj.truecolor = obj.acc.charCodeAt(7);
+ obj.rmax = ReadShort(obj.acc, 8);
+ obj.gmax = ReadShort(obj.acc, 10);
+ obj.bmax = ReadShort(obj.acc, 12);
+ obj.rsh = obj.acc.charCodeAt(14);
+ obj.gsh = obj.acc.charCodeAt(15);
+ obj.bsh = obj.acc.charCodeAt(16);
+ var name = obj.acc.substring(24, 24 + namelen);
+ obj.Debug("name: " + name);
+ obj.Debug("width: " + obj.width + ", height: " + obj.height);
+ obj.Debug("bits-per-pixel: " + obj.xbpp);
+ obj.Debug("depth: " + obj.depth);
+ obj.Debug("big-endian-flag: " + obj.bigend);
+ obj.Debug("true-colour-flag: " + obj.truecolor);
+ obj.Debug("rgb max: " + obj.rmax + "," + obj.gmax + "," + obj.bmax);
+ obj.Debug("rgb shift: " + obj.rsh + "," + obj.gsh + "," + obj.bsh);
+ */
+
+ // SetEncodings, with AMT we can't omit RAW, must be specified.
+ // Intel AMT supports encodings: RAW (0), ZRLE (16), Desktop Size (0xFFFFFF21, -223), KVM Data Channel (1092)
+
+ var supportedEncodings = '';
+ if (obj.useZRLE) supportedEncodings += IntToStr(16);
+ supportedEncodings += IntToStr(0);
+ // ###BEGIN###{DesktopInband}
+ supportedEncodings += IntToStr(1092);
+ // ###END###{DesktopInband}
+
+ obj.Send(String.fromCharCode(2, 0) + ShortToStr((supportedEncodings.length / 4) + 1) + supportedEncodings + IntToStr(-223)); // Supported Encodings + Desktop Size
+
+ if (obj.graymode == 0) {
+ // Set the pixel encoding to something much smaller
+ // obj.Send(String.fromCharCode(0, 0, 0, 0, 16, 16, 0, 1) + ShortToStr(31) + ShortToStr(63) + ShortToStr(31) + String.fromCharCode(11, 5, 0, 0, 0, 0)); // Setup 16 bit color RGB565 (This is the default, so we don't need to set it)
+ if (obj.bpp == 1) obj.Send(String.fromCharCode(0, 0, 0, 0, 8, 8, 0, 1) + ShortToStr(7) + ShortToStr(7) + ShortToStr(3) + String.fromCharCode(5, 2, 0, 0, 0, 0)); // Setup 8 bit color RGB332
+ } else {
+ obj.bpp = 1;
+ if (obj.graymode == 1) { obj.Send(String.fromCharCode(0, 0, 0, 0, 8, 8, 0, 1) + ShortToStr(255) + ShortToStr(0) + ShortToStr(0) + String.fromCharCode(0, 0, 0, 0, 0, 0)); } // Setup 8 bit gray RGB800
+ if (obj.graymode == 2) { obj.Send(String.fromCharCode(0, 0, 0, 0, 8, 8, 0, 1) + ShortToStr(15) + ShortToStr(0) + ShortToStr(0) + String.fromCharCode(0, 0, 0, 0, 0, 0)); } // Setup 4 bit gray RGB400
+ }
+
+ obj.state = 4;
+ if (obj.parent) { obj.parent.xxStateChange(3); }
+ _SendRefresh();
+ //obj.timer = setInterval(obj.xxOnTimer, 50);
+
+ // ###BEGIN###{DesktopFocus}
+ obj.ox = -1; // Old mouse x position
+ // ###END###{DesktopFocus}
+
+ if (obj.onScreenSizeChange != null) { obj.onScreenSizeChange(obj, obj.ScreenWidth, obj.ScreenHeight); }
+ }
+ else if (obj.state == 4) {
+ switch (obj.acc.charCodeAt(0)) {
+ case 0: // FramebufferUpdate
+ if (obj.acc.length < 4) return;
+ obj.state = 100 + ReadShort(obj.acc, 2); // Read the number of tiles that are going to be sent, add 100 and use that as our protocol state.
+ cmdsize = 4;
+ break;
+ case 2: // This is the bell, do nothing.
+ cmdsize = 1;
+ break;
+ case 3: // This is ServerCutText
+ if (obj.acc.length < 8) return;
+ var len = ReadInt(obj.acc, 4) + 8;
+ if (obj.acc.length < len) return;
+ cmdsize = handleServerCutText(obj.acc);
+ break;
+ }
+ }
+ else if (obj.state > 100 && obj.acc.length >= 12) {
+ var x = ReadShort(obj.acc, 0),
+ y = ReadShort(obj.acc, 2),
+ width = ReadShort(obj.acc, 4),
+ height = ReadShort(obj.acc, 6),
+ s = width * height,
+ encoding = ReadInt(obj.acc, 8);
+
+ if (encoding < 17) {
+ if (width < 1 || width > 64 || height < 1 || height > 64) { console.log("Invalid tile size (" + width + "," + height + "), disconnecting."); return obj.Stop(); }
+
+ // Set the spare bitmap to the right size if it's not already. This allows us to recycle the spare most if not all the time.
+ if (obj.sparew != width || obj.spareh != height) {
+ obj.sparew = obj.sparew2 = width;
+ obj.spareh = obj.spareh2 = height;
+ // ###BEGIN###{DesktopRotation}
+ if (obj.rotation == 1 || obj.rotation == 3) { obj.sparew2 = height, obj.spareh2 = width; }
+ // ###END###{DesktopRotation}
+ var xspacecachename = obj.sparew2 + 'x' + obj.spareh2;
+ obj.spare = obj.sparecache[xspacecachename];
+ if (!obj.spare) {
+ obj.sparecache[xspacecachename] = obj.spare = obj.canvas.createImageData(obj.sparew2, obj.spareh2);
+ var j = (obj.sparew2 * obj.spareh2) << 2;
+ for (var i = 3; i < j; i += 4) { obj.spare.data[i] = 0xFF; } // Set alpha channel to opaque.
+ }
+ }
+
+ }
+
+ if (encoding == 0xFFFFFF21) {
+ // Desktop Size (0xFFFFFF21, -223)
+ obj.canvas.canvas.width = obj.ScreenWidth = obj.rwidth = obj.width = width;
+ obj.canvas.canvas.height = obj.ScreenHeight = obj.rheight = obj.height = height;
+ obj.Send(String.fromCharCode(3, 0, 0, 0, 0, 0) + ShortToStr(obj.width) + ShortToStr(obj.height)); // FramebufferUpdateRequest
+ cmdsize = 12;
+ if (obj.onScreenSizeChange != null) { obj.onScreenSizeChange(obj, obj.ScreenWidth, obj.ScreenHeight); }
+ // obj.Debug("New desktop width: " + obj.width + ", height: " + obj.height);
+ }
+ else if (encoding == 0) {
+ // RAW encoding
+ var ptr = 12, cs = 12 + (s * obj.bpp);
+ if (obj.acc.length < cs) return; // Check we have all the data needed and we can only draw 64x64 tiles.
+ cmdsize = cs;
+
+ // CRITICAL LOOP, optimize this as much as possible
+ if (obj.bpp == 2) {
+ for (var i = 0; i < s; i++) { _setPixel16(obj.acc.charCodeAt(ptr++) + (obj.acc.charCodeAt(ptr++) << 8), i); }
+ } else {
+ for (var i = 0; i < s; i++) { _setPixel8(obj.acc.charCodeAt(ptr++), i); }
+ }
+ _putImage(obj.spare, x, y);
+ }
+ else if (encoding == 16) {
+ // ZRLE encoding
+ if (obj.acc.length < 16) return;
+ var datalen = ReadInt(obj.acc, 12);
+ if (obj.acc.length < (16 + datalen)) return;
+ //obj.Debug("RECT ZRLE (" + x + "," + y + "," + width + "," + height + ") LEN = " + datalen);
+ //obj.Debug("RECT ZRLE LEN: " + ReadShortX(obj.acc, 17) + ", DATA: " + rstr2hex(obj.acc.substring(16)));
+
+ // Process the ZLib header if this is the first block
+ var ptr = 16, delta = 5, dx = 0;
+
+ if (datalen > 5 && obj.acc.charCodeAt(ptr) == 0 && ReadShortX(obj.acc, ptr + 1) == (datalen - delta)) {
+ // This is an uncompressed ZLib data block
+ _decodeLRE(obj.acc, ptr + 5, x, y, width, height, s, datalen);
+ }
+ // ###BEGIN###{Inflate}
+ else {
+ // This is compressed ZLib data, decompress and process it.
+ var arr = obj.inflate.inflate(obj.acc.substring(ptr, ptr + datalen - dx));
+ if (arr.length > 0) { _decodeLRE(arr, 0, x, y, width, height, s, arr.length); } else { obj.Debug("Invalid deflate data"); }
+ }
+ // ###END###{Inflate}
+
+ cmdsize = 16 + datalen;
+ } else {
+ obj.Debug('Unknown Encoding: ' + encoding + ', HEX: ' + rstr2hex(obj.acc));
+ return obj.Stop();
+ }
+ if (--obj.state == 100) {
+ obj.state = 4;
+ if (obj.frameRateDelay == 0) {
+ _SendRefresh(); // Ask for new frame
+ } else {
+ setTimeout(_SendRefresh, obj.frameRateDelay); // Hold x miliseconds before asking for a new frame
+ }
+ }
+ }
+
+ if (cmdsize == 0) return;
+ obj.acc = obj.acc.substring(cmdsize);
+ }
+ }
+
+ function _decodeLRE(data, ptr, x, y, width, height, s, datalen) {
+ var subencoding = data.charCodeAt(ptr++), index, v, runlengthdecode, palette = {}, rlecount = 0, runlength = 0, i;
+ // obj.Debug("RECT RLE (" + (datalen - 5) + ", " + subencoding + "):" + rstr2hex(data.substring(21, 21 + (datalen - 5))));
+ if (subencoding == 0) {
+ // RAW encoding
+ if (obj.bpp == 2) {
+ for (i = 0; i < s; i++) { _setPixel16(data.charCodeAt(ptr++) + (data.charCodeAt(ptr++) << 8), i); }
+ } else {
+ for (i = 0; i < s; i++) { _setPixel8(data.charCodeAt(ptr++), i); }
+ }
+ _putImage(obj.spare, x, y);
+ }
+ else if (subencoding == 1) {
+ // Solid color tile
+ v = data.charCodeAt(ptr++) + ((obj.bpp == 2) ? (data.charCodeAt(ptr++) << 8) : 0);
+ obj.canvas.fillStyle = 'rgb(' + ((obj.bpp == 1) ? ((v & 224) + ',' + ((v & 28) << 3) + ',' + _fixColor((v & 3) << 6)) : (((v >> 8) & 248) + ',' + ((v >> 3) & 252) + ',' + ((v & 31) << 3))) + ')';
+
+ // ###BEGIN###{DesktopRotation}
+ var xx = _rotX(x, y);
+ y = _rotY(x, y);
+ x = xx;
+ // ###END###{DesktopRotation}
+
+ obj.canvas.fillRect(x, y, width, height);
+ }
+ else if (subencoding > 1 && subencoding < 17) { // Packed palette encoded tile
+ // Read the palette
+ var br = 4, bm = 15; // br is BitRead and bm is BitMask. By adjusting these two we can support all the variations in this encoding.
+ if (obj.bpp == 2) {
+ for (i = 0; i < subencoding; i++) { palette[i] = data.charCodeAt(ptr++) + (data.charCodeAt(ptr++) << 8); }
+ if (subencoding == 2) { br = 1; bm = 1; } else if (subencoding <= 4) { br = 2; bm = 3; } // Compute bits to read & bit mark
+ while (rlecount < s && ptr < data.length) { v = data.charCodeAt(ptr++); for (i = (8 - br) ; i >= 0; i -= br) { _setPixel16(palette[(v >> i) & bm], rlecount++); } } // Display all the bits
+ } else {
+ for (i = 0; i < subencoding; i++) { palette[i] = data.charCodeAt(ptr++); }
+ if (subencoding == 2) { br = 1; bm = 1; } else if (subencoding <= 4) { br = 2; bm = 3; } // Compute bits to read & bit mark
+ while (rlecount < s && ptr < data.length) { v = data.charCodeAt(ptr++); for (i = (8 - br) ; i >= 0; i -= br) { _setPixel8(palette[(v >> i) & bm], rlecount++); } } // Display all the bits
+ }
+ _putImage(obj.spare, x, y);
+ }
+ else if (subencoding == 128) { // RLE encoded tile
+ if (obj.bpp == 2) {
+ while (rlecount < s && ptr < data.length) {
+ // Get the run color
+ v = data.charCodeAt(ptr++) + (data.charCodeAt(ptr++) << 8);
+
+ // Decode the run length. This is the fastest and most compact way I found to do this.
+ runlength = 1; do { runlength += (runlengthdecode = data.charCodeAt(ptr++)); } while (runlengthdecode == 255);
+
+ // Draw a run
+ if (obj.rotation == 0) {
+ _setPixel16run(v, rlecount, runlength); rlecount += runlength;
+ } else {
+ while (--runlength >= 0) { _setPixel16(v, rlecount++); }
+ }
+ }
+ } else {
+ while (rlecount < s && ptr < data.length) {
+ // Get the run color
+ v = data.charCodeAt(ptr++);
+
+ // Decode the run length. This is the fastest and most compact way I found to do this.
+ runlength = 1; do { runlength += (runlengthdecode = data.charCodeAt(ptr++)); } while (runlengthdecode == 255);
+
+ // Draw a run
+ if (obj.rotation == 0) {
+ _setPixel8run(v, rlecount, runlength); rlecount += runlength;
+ } else {
+ while (--runlength >= 0) { _setPixel8(v, rlecount++); }
+ }
+ }
+ }
+ _putImage(obj.spare, x, y);
+ }
+ else if (subencoding > 129) { // Palette RLE encoded tile
+ // Read the palette
+ if (obj.bpp == 2) {
+ for (i = 0; i < (subencoding - 128) ; i++) { palette[i] = data.charCodeAt(ptr++) + (data.charCodeAt(ptr++) << 8); }
+ } else {
+ for (i = 0; i < (subencoding - 128) ; i++) { palette[i] = data.charCodeAt(ptr++); }
+ }
+
+ // Decode RLE on palette
+ while (rlecount < s && ptr < data.length) {
+ // Setup the run, get the color index and get the color from the palette.
+ runlength = 1; index = data.charCodeAt(ptr++); v = palette[index % 128];
+
+ // If the index starts with high order bit 1, this is a run and decode the run length.
+ if (index > 127) { do { runlength += (runlengthdecode = data.charCodeAt(ptr++)); } while (runlengthdecode == 255); }
+
+ // Draw a run
+ if (obj.rotation == 0) {
+ if (obj.bpp == 2) {
+ _setPixel16run(v, rlecount, runlength); rlecount += runlength;
+ } else {
+ _setPixel8run(v, rlecount, runlength); rlecount += runlength;
+ }
+ } else {
+ if (obj.bpp == 2) {
+ while (--runlength >= 0) { _setPixel16(v, rlecount++); }
+ } else {
+ while (--runlength >= 0) { _setPixel8(v, rlecount++); }
+ }
+ }
+ }
+ _putImage(obj.spare, x, y);
+ }
+ }
+
+ // ###BEGIN###{DesktopInband}
+ obj.hold = function (holding) {
+ if (obj.holding == holding) return;
+ obj.holding = holding;
+ obj.canvas.fillStyle = '#000000';
+ obj.canvas.fillRect(0, 0, obj.width, obj.height); // Paint black
+ if (obj.holding == false) {
+ // Go back to normal operations
+ // Set canvas size and ask for full screen refresh
+ if ((obj.canvas.canvas.width != obj.width) || (obj.canvas.canvas.height != obj.height)) {
+ obj.canvas.canvas.width = obj.width; obj.canvas.canvas.height = obj.height;
+ if (obj.onScreenSizeChange != null) { obj.onScreenSizeChange(obj, obj.ScreenWidth, obj.ScreenHeight); } // ???
+ }
+ obj.Send(String.fromCharCode(3, 0, 0, 0, 0, 0) + ShortToStr(obj.width) + ShortToStr(obj.height)); // FramebufferUpdateRequest
+ } else {
+ obj.UnGrabMouseInput();
+ obj.UnGrabKeyInput();
+ }
+ }
+ // ###END###{DesktopInband}
+
+ function _putImage(i, x, y) {
+ // ###BEGIN###{DesktopInband}
+ if (obj.holding == true) return;
+ // ###END###{DesktopInband}
+ // ###BEGIN###{DesktopRotation}
+ var xx = _arotX(x, y);
+ y = _arotY(x, y);
+ x = xx;
+ // ###END###{DesktopRotation}
+ obj.canvas.putImageData(i, x, y);
+ }
+
+ // Set 8bit color RGB332
+ function _setPixel8(v, p) {
+ var pp = p << 2;
+
+ // ###BEGIN###{DesktopRotation}
+ if (obj.rotation > 0) {
+ if (obj.rotation == 1) { var x = p % obj.sparew, y = Math.floor(p / obj.sparew); p = (x * obj.sparew2) + (obj.sparew2 - 1 - y); pp = p << 2; }
+ else if (obj.rotation == 2) { pp = (obj.sparew * obj.spareh * 4) - 4 - pp; }
+ else if (obj.rotation == 3) { var x = p % obj.sparew, y = Math.floor(p / obj.sparew); p = ((obj.sparew2 - 1 - x) * obj.sparew2) + (y); pp = p << 2; }
+ }
+ // ###END###{DesktopRotation}
+
+ if (obj.graymode == 0) {
+ obj.spare.data[pp] = v & 224;
+ obj.spare.data[pp + 1] = (v & 28) << 3;
+ obj.spare.data[pp + 2] = _fixColor((v & 3) << 6);
+ } else {
+ obj.spare.data[pp] = obj.spare.data[pp + 1] = obj.spare.data[pp + 2] = v;
+ }
+ }
+
+ // Set 16bit color RGB565
+ function _setPixel16(v, p) {
+ var pp = p << 2;
+
+ // ###BEGIN###{DesktopRotation}
+ if (obj.rotation > 0) {
+ if (obj.rotation == 1) { var x = p % obj.sparew, y = Math.floor(p / obj.sparew); p = (x * obj.sparew2) + (obj.sparew2 - 1 - y); pp = p << 2; }
+ else if (obj.rotation == 2) { pp = (obj.sparew * obj.spareh * 4) - 4 - pp; }
+ else if (obj.rotation == 3) { var x = p % obj.sparew, y = Math.floor(p / obj.sparew); p = ((obj.sparew2 - 1 - x) * obj.sparew2) + (y); pp = p << 2; }
+ }
+ // ###END###{DesktopRotation}
+
+ obj.spare.data[pp] = (v >> 8) & 248;
+ obj.spare.data[pp + 1] = (v >> 3) & 252;
+ obj.spare.data[pp + 2] = (v & 31) << 3;
+ }
+
+ // Set a run of 8bit color RGB332
+ function _setPixel8run(v, p, run) {
+ var pp = (p << 2), r = (v & 224), g = ((v & 28) << 3), b = (_fixColor((v & 3) << 6));
+ while (--run >= 0) { obj.spare.data[pp] = r; obj.spare.data[pp+1] = g; obj.spare.data[pp+2] = b; pp += 4; }
+ }
+
+ // Set a run of 16bit color RGB565
+ function _setPixel16run(v, p, run) {
+ var pp = (p << 2), r = ((v >> 8) & 248), g = ((v >> 3) & 252), b = ((v & 31) << 3);
+ while (--run >= 0) { obj.spare.data[pp] = r; obj.spare.data[pp+1] = g; obj.spare.data[pp+2] = b; pp += 4; }
+ }
+
+ // ###BEGIN###{DesktopRotation}
+ function _arotX(x, y) {
+ if (obj.rotation == 0) return x;
+ if (obj.rotation == 1) return obj.canvas.canvas.width - obj.sparew2 - y;
+ if (obj.rotation == 2) return obj.canvas.canvas.width - obj.sparew2 - x;
+ if (obj.rotation == 3) return y;
+ return 0;
+ }
+
+ function _arotY(x, y) {
+ if (obj.rotation == 0) return y;
+ if (obj.rotation == 1) return x;
+ if (obj.rotation == 2) return obj.canvas.canvas.height - obj.spareh2 - y;
+ if (obj.rotation == 3) return obj.canvas.canvas.height - obj.spareh - x;
+ return 0;
+ }
+
+ function _crotX(x, y) {
+ if (obj.rotation == 0) return x;
+ if (obj.rotation == 1) return y;
+ if (obj.rotation == 2) return obj.canvas.canvas.width - x;
+ if (obj.rotation == 3) return obj.canvas.canvas.height - y;
+ return 0;
+ }
+
+ function _crotY(x, y) {
+ if (obj.rotation == 0) return y;
+ if (obj.rotation == 1) return obj.canvas.canvas.width - x;
+ if (obj.rotation == 2) return obj.canvas.canvas.height - y;
+ if (obj.rotation == 3) return x;
+ return 0;
+ }
+
+ function _rotX(x, y) {
+ if (obj.rotation == 0) return x;
+ if (obj.rotation == 1) return x;
+ if (obj.rotation == 2) return x - obj.canvas.canvas.width;
+ if (obj.rotation == 3) return x - obj.canvas.canvas.height;
+ return 0;
+ }
+
+ function _rotY(x, y) {
+ if (obj.rotation == 0) return y;
+ if (obj.rotation == 1) return y - obj.canvas.canvas.width;
+ if (obj.rotation == 2) return y - obj.canvas.canvas.height;
+ if (obj.rotation == 3) return y;
+ return 0;
+ }
+
+ obj.tcanvas = null;
+ obj.setRotation = function (x) {
+ while (x < 0) { x += 4; }
+ var newrotation = x % 4;
+ //console.log('hard-rot: ' + newrotation);
+ // ###BEGIN###{DesktopInband}
+ if (obj.holding == true) { obj.rotation = newrotation; return; }
+ // ###END###{DesktopInband}
+
+ if (newrotation == obj.rotation) return true;
+ var rw = obj.canvas.canvas.width;
+ var rh = obj.canvas.canvas.height;
+ if (obj.rotation == 1 || obj.rotation == 3) { rw = obj.canvas.canvas.height; rh = obj.canvas.canvas.width; }
+
+ // Copy the canvas, put it back in the correct direction
+ if (obj.tcanvas == null) obj.tcanvas = document.createElement('canvas');
+ var tcanvasctx = obj.tcanvas.getContext('2d');
+ tcanvasctx.setTransform(1, 0, 0, 1, 0, 0);
+ tcanvasctx.canvas.width = rw;
+ tcanvasctx.canvas.height = rh;
+ tcanvasctx.rotate((obj.rotation * -90) * Math.PI / 180);
+ if (obj.rotation == 0) tcanvasctx.drawImage(obj.canvas.canvas, 0, 0);
+ if (obj.rotation == 1) tcanvasctx.drawImage(obj.canvas.canvas, -obj.canvas.canvas.width, 0);
+ if (obj.rotation == 2) tcanvasctx.drawImage(obj.canvas.canvas, -obj.canvas.canvas.width, -obj.canvas.canvas.height);
+ if (obj.rotation == 3) tcanvasctx.drawImage(obj.canvas.canvas, 0, -obj.canvas.canvas.height);
+
+ // Change the size and orientation and copy the canvas back into the rotation
+ if (obj.rotation == 0 || obj.rotation == 2) { obj.canvas.canvas.height = rw; obj.canvas.canvas.width = rh; }
+ if (obj.rotation == 1 || obj.rotation == 3) { obj.canvas.canvas.height = rh; obj.canvas.canvas.width = rw; }
+ obj.canvas.setTransform(1, 0, 0, 1, 0, 0);
+ obj.canvas.rotate((newrotation * 90) * Math.PI / 180);
+ obj.rotation = newrotation;
+ obj.canvas.drawImage(obj.tcanvas, _rotX(0, 0), _rotY(0, 0));
+
+ obj.width = obj.canvas.canvas.width;
+ obj.height = obj.canvas.canvas.height;
+ if (obj.onScreenResize != null) obj.onScreenResize(obj, obj.width, obj.height, obj.CanvasId);
+ return true;
+ }
+ // ###END###{DesktopRotation}
+
+ function _fixColor(c) { return (c > 127) ? (c + 32) : c; }
+
+ function _SendRefresh() {
+ // ###BEGIN###{DesktopInband}
+ if (obj.holding == true) return;
+ // ###END###{DesktopInband}
+ // ###BEGIN###{DesktopFocus}
+ if (obj.focusmode > 0) {
+ // Request only pixels around the last mouse position
+ var df = obj.focusmode * 2;
+ obj.Send(String.fromCharCode(3, 1) + ShortToStr(Math.max(Math.min(obj.ox, obj.mx) - obj.focusmode, 0)) + ShortToStr(Math.max(Math.min(obj.oy, obj.my) - obj.focusmode, 0)) + ShortToStr(df + Math.abs(obj.ox - obj.mx)) + ShortToStr(df + Math.abs(obj.oy - obj.my))); // FramebufferUpdateRequest
+ obj.ox = obj.mx;
+ obj.oy = obj.my;
+ } else {
+ // ###END###{DesktopFocus}
+ // Request the entire screen
+ obj.Send(String.fromCharCode(3, 1, 0, 0, 0, 0) + ShortToStr(obj.rwidth) + ShortToStr(obj.rheight)); // FramebufferUpdateRequest
+ // ###BEGIN###{DesktopFocus}
+ }
+ // ###END###{DesktopFocus}
+ }
+
+ obj.Start = function () {
+ //obj.Debug("KVM-Start");
+ obj.state = 0;
+ obj.acc = "";
+ obj.ZRLEfirst = 1;
+ //obj.inbytes = 0;
+ //obj.outbytes = 0;
+ // ###BEGIN###{Inflate}
+ obj.inflate.inflateReset();
+ // ###END###{Inflate}
+ // ###BEGIN###{DesktopInband}
+ obj.onKvmDataPending = [];
+ obj.onKvmDataAck = -1;
+ obj.kvmDataSupported = false;
+ // ###END###{DesktopInband}
+ for (var i in obj.sparecache) { delete obj.sparecache[i]; }
+ }
+
+ obj.Stop = function () {
+ obj.UnGrabMouseInput();
+ obj.UnGrabKeyInput();
+ if (obj.parent) { obj.parent.Stop(); }
+ }
+
+ obj.Send = function (x) {
+ //obj.Debug("KSend(" + x.length + "): " + rstr2hex(x));
+ //obj.outbytes += x.length;
+ if (obj.parent) { obj.parent.Send(x); }
+ }
+
+ var convertAmtKeyCodeTable = {
+ "Pause": 19,
+ "CapsLock": 20,
+ "Space": 32,
+ "Quote": 39,
+ "Minus": 45,
+ "NumpadMultiply": 42,
+ "NumpadAdd": 43,
+ "PrintScreen": 44,
+ "Comma": 44,
+ "NumpadSubtract": 45,
+ "NumpadDecimal": 46,
+ "Period": 46,
+ "Slash": 47,
+ "NumpadDivide": 47,
+ "Semicolon": 59,
+ "Equal": 61,
+ "OSLeft": 91,
+ "BracketLeft": 91,
+ "OSRight": 91,
+ "Backslash": 92,
+ "BracketRight": 93,
+ "ContextMenu": 93,
+ "Backquote": 96,
+ "NumLock": 144,
+ "ScrollLock": 145,
+ "Backspace": 0xff08,
+ "Tab": 0xff09,
+ "Enter": 0xff0d,
+ "NumpadEnter": 0xff0d,
+ "Escape": 0xff1b,
+ "Delete": 0xffff,
+ "Home": 0xff50,
+ "PageUp": 0xff55,
+ "PageDown": 0xff56,
+ "ArrowLeft": 0xff51,
+ "ArrowUp": 0xff52,
+ "ArrowRight": 0xff53,
+ "ArrowDown": 0xff54,
+ "End": 0xff57,
+ "Insert": 0xff63,
+ "F1": 0xffbe,
+ "F2": 0xffbf,
+ "F3": 0xffc0,
+ "F4": 0xffc1,
+ "F5": 0xffc2,
+ "F6": 0xffc3,
+ "F7": 0xffc4,
+ "F8": 0xffc5,
+ "F9": 0xffc6,
+ "F10": 0xffc7,
+ "F11": 0xffc8,
+ "F12": 0xffc9,
+ "ShiftLeft": 0xffe1,
+ "ShiftRight": 0xffe2,
+ "ControlLeft": 0xffe3,
+ "ControlRight": 0xffe4,
+ "AltLeft": 0xffe9,
+ "AltRight": 0xffea,
+ "MetaLeft": 0xffe7,
+ "MetaRight": 0xffe8
+ }
+ function convertAmtKeyCode(e) {
+ if (e.code.startsWith('Key') && e.code.length == 4) { return e.code.charCodeAt(3) + ((e.shiftKey == false) ? 32 : 0); }
+ if (e.code.startsWith('Digit') && e.code.length == 6) { return e.code.charCodeAt(5); }
+ if (e.code.startsWith('Numpad') && e.code.length == 7) { return e.code.charCodeAt(6); }
+ return convertAmtKeyCodeTable[e.code];
+ }
+
+ /*
+ Intel AMT only recognizes a small subset of keysym characters defined in the keysymdef.h so you don’t need to
+ implement all the languages (this is taken care by the USB Scancode Extension in RFB4.0 protocol).
+ The only subset recognized by the FW is the defined by the following sets : XK_LATIN1 , XK_MISCELLANY, XK_3270, XK_XKB_KEYS, XK_KATAKANA.
+ In addition to keysymdef.h symbols there are 6 japanese extra keys that we do support:
+
+ #define XK_Intel_EU_102kbd_backslash_pipe_45 0x17170056 // European 102-key: 45 (backslash/pipe), usb Usage: 0x64
+ #define XK_Intel_JP_106kbd_yen_pipe 0x1717007d // Japanese 106-key: 14 (Yen/pipe), usb Usage: 0x89
+ #define XK_Intel_JP_106kbd_backslash_underbar 0x17170073 // Japanese 106-key: 56 (backslash/underbar), usb Usage: 0x87
+ #define XK_Intel_JP_106kbd_NoConvert 0x1717007b // Japanese 106-key: 131 (NoConvert), usb Usage: 0x8b
+ #define XK_Intel_JP_106kbd_Convert 0x17170079 // Japanese 106-key: 132 (Convert), usb Usage: 0x8a
+ #define XK_Intel_JP_106kbd_Hirigana_Katakana 0x17170070 // Japanese 106-key: 133 (Hirigana/Katakana), usb Usage: 0x88
+ */
+
+ function _keyevent(d, e) {
+ if (!e) { e = window.event; }
+
+ if (e.code) {
+ // For new browsers, this mapping is keyboard language independent
+ var k = convertAmtKeyCode(e);
+ if (k != null) { obj.sendkey(k, d); }
+ } else {
+ var k = e.keyCode;
+ if (k == 173) k = 189; // '-' key (Firefox)
+ if (k == 61) k = 187; // '=' key (Firefox)
+ var kk = k;
+ if (e.shiftKey == false && k >= 65 && k <= 90) kk = k + 32;
+ if (k >= 112 && k <= 124) kk = k + 0xFF4E;
+ if (k == 8) kk = 0xff08; // Backspace
+ if (k == 9) kk = 0xff09; // Tab
+ if (k == 13) kk = 0xff0d; // Return
+ if (k == 16) kk = 0xffe1; // Shift (Left)
+ if (k == 17) kk = 0xffe3; // Ctrl (Left)
+ if (k == 18) kk = 0xffe9; // Alt (Left)
+ if (k == 27) kk = 0xff1b; // ESC
+ if (k == 33) kk = 0xff55; // PageUp
+ if (k == 34) kk = 0xff56; // PageDown
+ if (k == 35) kk = 0xff57; // End
+ if (k == 36) kk = 0xff50; // Home
+ if (k == 37) kk = 0xff51; // Left
+ if (k == 38) kk = 0xff52; // Up
+ if (k == 39) kk = 0xff53; // Right
+ if (k == 40) kk = 0xff54; // Down
+ if (k == 45) kk = 0xff63; // Insert
+ if (k == 46) kk = 0xffff; // Delete
+ if (k >= 96 && k <= 105) kk = k - 48; // Key pad numbers
+ if (k == 106) kk = 42; // Pad *
+ if (k == 107) kk = 43; // Pad +
+ if (k == 109) kk = 45; // Pad -
+ if (k == 110) kk = 46; // Pad .
+ if (k == 111) kk = 47; // Pad /
+ if (k == 186) kk = 59; // ;
+ if (k == 187) kk = 61; // =
+ if (k == 188) kk = 44; // ,
+ if (k == 189) kk = 45; // -
+ if (k == 190) kk = 46; // .
+ if (k == 191) kk = 47; // /
+ if (k == 192) kk = 96; // `
+ if (k == 219) kk = 91; // [
+ if (k == 220) kk = 92; // \
+ if (k == 221) kk = 93; // ]t
+ if (k == 222) kk = 39; // '
+ //console.log('Key' + d + ": " + k + " = " + kk);
+ obj.sendkey(kk, d);
+ }
+ return obj.haltEvent(e);
+ }
+
+ obj.sendkey = function (k, d) {
+ if (typeof k == 'object') { for (var i in k) { obj.sendkey(k[i][0], k[i][1]); } }
+ else { obj.Send(String.fromCharCode(4, d, 0, 0) + IntToStr(k)); }
+ }
+
+ function handleServerCutText(acc) {
+ if (acc.length < 8) return 0;
+ var len = ReadInt(obj.acc, 4) + 8;
+ if (acc.length < len) return 0;
+ // ###BEGIN###{DesktopInband}
+ if (obj.onKvmData != null) {
+ var d = acc.substring(8, len);
+ if ((d.length >= 16) && (d.substring(0, 15) == '\0KvmDataChannel')) {
+ if (obj.kvmDataSupported == false) { obj.kvmDataSupported = true; console.log('KVM Data Channel Supported.'); }
+ if (((obj.onKvmDataAck == -1) && (d.length == 16)) || (d.charCodeAt(15) != 0)) { obj.onKvmDataAck = true; }
+ if (urlvars && urlvars['kvmdatatrace']) { console.log('KVM-Recv(' + (d.length - 16) + '): ' + d.substring(16)); }
+ if (d.length > 16) { obj.onKvmData(d.substring(16)); } // Event the data and ack
+ if ((obj.onKvmDataAck == true) && (obj.onKvmDataPending.length > 0)) { obj.sendKvmData(obj.onKvmDataPending.shift()); } // Send pending data
+ }
+ }
+ // ###END###{DesktopInband}
+ return len;
+ }
+
+ // ###BEGIN###{DesktopInband}
+ obj.sendKvmData = function (x) {
+ if (obj.onKvmDataAck !== true) {
+ obj.onKvmDataPending.push(x);
+ } else {
+ if (urlvars && urlvars['kvmdatatrace']) { console.log('KVM-Send(' + x.length + '): ' + x); }
+ x = '\0KvmDataChannel\0' + x;
+ obj.Send(String.fromCharCode(6, 0, 0, 0) + IntToStr(x.length) + x);
+ obj.onKvmDataAck = false;
+ }
+ }
+
+ // Send a HWKVM keep alive if it's not been sent in the last 5 seconds.
+ obj.sendKeepAlive = function () {
+ if (obj.lastKeepAlive < Date.now() - 5000) { obj.lastKeepAlive = Date.now(); obj.Send(String.fromCharCode(6, 0, 0, 0) + IntToStr(16) + '\0KvmDataChannel\0'); }
+ }
+ // ###END###{DesktopInband}
+
+ obj.SendCtrlAltDelMsg = function () { obj.sendcad(); }
+ obj.sendcad = function () {
+ obj.sendkey(0xFFE3, 1); // Control
+ obj.sendkey(0xFFE9, 1); // Alt
+ obj.sendkey(0xFFFF, 1); // Delete
+ obj.sendkey(0xFFFF, 0); // Delete
+ obj.sendkey(0xFFE9, 0); // Alt
+ obj.sendkey(0xFFE3, 0); // Control
+ }
+
+ var _MouseInputGrab = false;
+ var _KeyInputGrab = false;
+
+ obj.GrabMouseInput = function () {
+ if (_MouseInputGrab == true) return;
+ var c = obj.canvas.canvas;
+ c.onmouseup = obj.mouseup;
+ c.onmousedown = obj.mousedown;
+ c.onmousemove = obj.mousemove;
+ //if (navigator.userAgent.match(/mozilla/i)) c.DOMMouseScroll = obj.xxDOMMouseScroll; else c.onmousewheel = obj.xxMouseWheel;
+ _MouseInputGrab = true;
+ }
+
+ obj.UnGrabMouseInput = function () {
+ if (_MouseInputGrab == false) return;
+ var c = obj.canvas.canvas;
+ c.onmousemove = null;
+ c.onmouseup = null;
+ c.onmousedown = null;
+ //if (navigator.userAgent.match(/mozilla/i)) c.DOMMouseScroll = null; else c.onmousewheel = null;
+ _MouseInputGrab = false;
+ }
+
+ obj.GrabKeyInput = function () {
+ if (_KeyInputGrab == true) return;
+ document.onkeyup = obj.handleKeyUp;
+ document.onkeydown = obj.handleKeyDown;
+ document.onkeypress = obj.handleKeys;
+ _KeyInputGrab = true;
+ }
+
+ obj.UnGrabKeyInput = function () {
+ if (_KeyInputGrab == false) return;
+ document.onkeyup = null;
+ document.onkeydown = null;
+ document.onkeypress = null;
+ _KeyInputGrab = false;
+ }
+
+ obj.handleKeys = function (e) { return obj.haltEvent(e); }
+ obj.handleKeyUp = function (e) { return _keyevent(0, e); }
+ obj.handleKeyDown = function (e) { return _keyevent(1, e); }
+ obj.haltEvent = function (e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
+
+ // RFB "PointerEvent" and mouse handlers
+ obj.mousedown = function (e) { obj.buttonmask |= (1 << e.button); return obj.mousemove(e, 1); }
+ obj.mouseup = function (e) { obj.buttonmask &= (0xFFFF - (1 << e.button)); return obj.mousemove(e, 1); }
+ obj.mousemove = function (e, force) {
+ if (obj.state < 4) return true;
+ var pos = obj.getPositionOfControl(Q(obj.canvasid));
+ obj.mx = (e.pageX - pos[0]) * (obj.canvas.canvas.height / Q(obj.canvasid).offsetHeight);
+ obj.my = ((e.pageY - pos[1] + (scrolldiv ? scrolldiv.scrollTop : 0)) * (obj.canvas.canvas.width / Q(obj.canvasid).offsetWidth));
+
+ // ###BEGIN###{DesktopRotation}
+ if (obj.noMouseRotate != true) {
+ obj.mx2 = _crotX(obj.mx, obj.my);
+ obj.my = _crotY(obj.mx, obj.my);
+ obj.mx = obj.mx2;
+ }
+ // ###END###{DesktopRotation}
+
+ // This is the mouse motion nagle timer. Slow down the mouse motion event rate.
+ if (force == 1) {
+ obj.Send(String.fromCharCode(5, obj.buttonmask) + ShortToStr(obj.mx) + ShortToStr(obj.my));
+ if (obj.mNagleTimer != null) { clearTimeout(obj.mNagleTimer); obj.mNagleTimer = null; }
+ } else {
+ if (obj.mNagleTimer == null) {
+ obj.mNagleTimer = setTimeout(function () {
+ obj.Send(String.fromCharCode(5, obj.buttonmask) + ShortToStr(obj.mx) + ShortToStr(obj.my));
+ obj.mNagleTimer = null;
+ }, 50);
+ }
+ }
+
+ // ###BEGIN###{DesktopFocus}
+ // Update focus area if we are in focus mode
+ QV('DeskFocus', obj.focusmode);
+ if (obj.focusmode != 0) {
+ var x = Math.min(obj.mx, obj.canvas.canvas.width - obj.focusmode),
+ y = Math.min(obj.my, obj.canvas.canvas.height - obj.focusmode),
+ df = obj.focusmode * 2,
+ c = Q(obj.canvasid),
+ qx = c.offsetHeight / obj.canvas.canvas.height,
+ qy = c.offsetWidth / obj.canvas.canvas.width,
+ q = QS('DeskFocus'),
+ ppos = obj.getPositionOfControl(Q(obj.canvasid).parentElement);
+ q.left = (Math.max(((x - obj.focusmode) * qx), 0) + (pos[0] - ppos[0])) + 'px';
+ q.top = (Math.max(((y - obj.focusmode) * qy), 0) + (pos[1] - ppos[1])) + 'px';
+ q.width = ((df * qx) - 6) + 'px';
+ q.height = ((df * qx) - 6) + 'px';
+ }
+ // ###END###{DesktopFocus}
+
+ return obj.haltEvent(e);
+ }
+
+ obj.getPositionOfControl = function (Control) {
+ var Position = Array(2);
+ Position[0] = Position[1] = 0;
+ while (Control) {
+ Position[0] += Control.offsetLeft;
+ Position[1] += Control.offsetTop;
+ Control = Control.offsetParent;
+ }
+ return Position;
+ }
+
+ return obj;
+}
diff --git a/amt-ider-node-0.0.1.js b/amt-ider-node-0.0.1.js
new file mode 100644
index 0000000..ac72f0a
--- /dev/null
+++ b/amt-ider-node-0.0.1.js
@@ -0,0 +1,509 @@
+/**
+* @description Meshcentral
+* @author Ylian Saint-Hilaire
+* @version v0.0.1
+*/
+
+function CreateIMRSDKWrapper() {
+ var obj = {};
+
+ var _IMRSDK;
+ var _ImrSdkVersion;
+ var _ref = require("ref");
+ var _ffi = require("ffi");
+ var _struct = require('ref-struct');
+ var _arrayType = require('ref-array');
+ obj.pendingData = {};
+
+ // Callback from the native lib back into js (StdCall)
+ var uintPtr = _ref.refType('uint');
+ var OpenHandlerCallBack = _ffi.Callback('int', ['uint', 'uint'], _ffi.FFI_STDCALL, function (clientID, conID) { obj.pendingData[conID] = ''; return 0; });
+ var CloseHandlerCallBack = _ffi.Callback('int', ['uint'], _ffi.FFI_STDCALL, function (conID) { obj.pendingData[conID] = ''; return 0; });
+ var ReceiveHandlerCallBack = _ffi.Callback('int', ['pointer', uintPtr, 'uint'], _ffi.FFI_STDCALL, function (bufferPtr, lengthPtr, conID) {
+ try {
+ var bufferLen = lengthPtr.readUInt32LE(0), buffer = _ref.reinterpret(bufferPtr, bufferLen);
+ lengthPtr.writeUInt32LE(obj.pendingData[conID].length, 0);
+ for (var i = 0; i < obj.pendingData[conID].length; i++) { buffer[i] = obj.pendingData[conID].charCodeAt(i); }
+ //console.log("ReceiveHandlerCallBack(conID: " + conID + ", Len: " + obj.pendingData[conID].length + ")");
+ obj.pendingData[conID] = '';
+ } catch (e) { console.log(e); }
+ return 0;
+ });
+ var SendHandlerCallBack = _ffi.Callback('int', ['pointer', 'uint', 'uint'], _ffi.FFI_STDCALL, function (ptr, length, conID) {
+ try {
+ var buffer = _ref.reinterpret(ptr, length), str = '';
+ for (var i = 0; i < length; i++) { str += String.fromCharCode(buffer[i]); }
+ //console.log("SendHandlerCallBack(conID: " + conID + ", Len: " + length + ")");
+ obj.client.write(str, 'binary');
+ } catch (e) { console.log(e); }
+ return 0;
+ });
+
+ var _IMRVersion = _struct({ 'major': 'ushort', 'minor': 'ushort' });
+ var _IMRVersionPtr = _ref.refType(_IMRVersion);
+ var _IMRClientInfo = _struct({ 'type': 'int', 'ip': _arrayType('char', 128), 'guid': _arrayType('char', 16)});
+ var _IMRClientInfoPtr = _ref.refType(_IMRClientInfo);
+ var _ProxySettings = _struct({ 'type': 'int', 'server': _arrayType('char', 128), 'port': 'int', 'user': _arrayType('char', 128), 'pass': _arrayType('char', 128) });
+ var _TCPSessionParams = _struct({ 'user': _arrayType('char', 128), 'pass': _arrayType('char', 128) });
+ var _TCPSessionParamsPtr = _ref.refType(_TCPSessionParams);
+ var _TCPSessionParamsEx = _struct({ 'version': 'int', 'user': _arrayType('char', 128), 'pass': _arrayType('char', 128), 'proxy': _ProxySettings });
+ var _TCPSessionParamsExPtr = _ref.refType(_TCPSessionParamsEx);
+ var _TCPSessionParamsEx2 = _struct({ 'version': 'int', 'user': _arrayType('char', 128), 'pass': _arrayType('char', 128), 'domain': _arrayType('char', 254), 'proxy': _ProxySettings });
+ var _TCPSessionParamsEx2Ptr = _ref.refType(_TCPSessionParamsEx2);
+ var _FeaturesSupported = _struct({ 'ider_dev_pri': 'int', 'ider_dev_sec': 'int', 'reserved': _arrayType('char', 30) });
+ var _FeaturesSupportedPtr = _ref.refType(_FeaturesSupported);
+ var _IDERTout = _struct({ 'rx_timeout': 'ushort', 'tx_timeout': 'ushort', 'hb_timeout': 'ushort' });
+ var _IDERToutPtr = _ref.refType(_IDERTout);
+ var _IDERStatistics = _struct({
+ 'error_state': 'int',
+ 'data_transfer': 'int',
+ 'num_reopen': 'ushort',
+ 'num_error': 'int',
+ 'num_reset': 'int',
+ 'last_cmd_length': 'int',
+ 'data_sent': 'int',
+ 'data_received': 'int',
+ 'packets_sent': 'int',
+ 'packets_received': 'int'
+ });
+ var _IDERStatisticsPtr = _ref.refType(_IDERStatistics);
+ var _IDERDeviceState = _struct({ 'pri_default': 'int', 'pri_current': 'int', 'sec_default': 'int', 'sec_current': 'int' });
+ var _IDERDeviceStatePtr = _ref.refType(_IDERDeviceState);
+ var _IDERDeviceCmd = _struct({ 'pri_op': 'int', 'pri_timing': 'int', 'sec_op': 'int', 'sec_timing': 'int' });
+ var _IDERDeviceCmdPtr = _ref.refType(_IDERDeviceCmd);
+ var _IDERDeviceResult = _struct({ 'pri_res': 'int', 'sec_res': 'int' });
+ var _IDERDeviceResultPtr = _ref.refType(_IDERDeviceResult);
+ var _SockCallBacks = _struct({ 'OpenHandler': 'pointer', 'CloseHandler': 'pointer', 'ReceiveHandler': 'pointer', 'SendHandler': 'pointer' });
+ var _SockCallBacksPtr = _ref.refType(_SockCallBacks);
+ var _intPtr = _ref.refType('int');
+
+ function _Setup(lib) {
+ try {
+ _IMRSDK = _ffi.Library(lib, {
+ "IMR_Init": ['uint', [_IMRVersionPtr, 'string']], // IMRResult IMR_Init(IMRVersion *version, char *ini_file);
+ "IMR_InitEx": ['uint', [_IMRVersionPtr, 'string', _SockCallBacksPtr]], // IMRResult IMR_Init(IMRVersion *version, char *ini_file, void *funcPtrs);
+ "IMR_ReadyReadSock": ['uint', ['uint']], // IMRResult IMR_ReadyReadSock(uint conid);
+ "IMR_Close": ['uint', []], // IMRResult IMR_Close();
+ "IMR_GetErrorStringLen": ['uint', ['uint', _intPtr]], // IMRResult IMR_GetErrorStringLen(IMRResult, int * str_len);
+ "IMR_GetErrorString": ['uint', ['uint', 'pointer']], // IMRResult IMR_GetErrorString(IMRResult, char * str);
+ "IMR_SetCertificateInfo": ['uint', ['string', 'string', 'string']], // IMRResult IMR_SetCertificateInfo(const char *root_cert, const char *private_cert, const char *cert_pass);
+ "IMR_SetClientCertificate": ['uint', ['string']], // IMRResult IMR_SetClientCertificate(const char *common_name);
+ "IMR_AddClient": ['uint', ['int', 'string', 'pointer', _intPtr]], // IMRResult IMR_AddClient(ClientType new_client_type, char * client_ip, GUIDType client_guid, ClientID * new_client_id);
+ "IMR_RemoveClient": ['uint', ['int']], // IMRResult IMR_RemoveClient(ClientID client_id);
+ "IMR_RemoveAllClients": ['uint', []], // IMRResult IMR_RemoveAllClients();
+ "IMR_GetAllClients": ['uint', [_arrayType('int'), _intPtr]], // IMRResult IMR_GetAllClients(ClientID * client_list, int * client_list_size);
+ "IMR_GetClientInfo": ['uint', ['int', _IMRClientInfoPtr]], // IMRResult IMR_GetClientInfo(ClientID client_id, ClientInfo *);
+ "IMR_IDEROpenTCPSession": ['uint', ['int', _TCPSessionParamsPtr, _IDERToutPtr, 'string', 'string']], // IMRResult IMR_IDEROpenTCPSession(ClientID client_id, TCPSessionParams * params, IDERTout * touts, char * drive0, char * drive1);
+ "IMR_IDEROpenTCPSessionEx": ['uint', ['int', _TCPSessionParamsExPtr, _IDERToutPtr, 'string', 'string']], // IMRResult IMR_IDEROpenTCPSessionEx(ClientID client_id, TCPSessionParamsEx * params, IDERTout * touts, char * drive0, char * drive1);
+ "IMR_IDEROpenTCPSessionEx2": ['uint', ['int', _TCPSessionParamsEx2Ptr, _IDERToutPtr, 'string', 'string']], // IMRResult IMR_IDEROpenTCPSessionEx2(ClientID client_id, TCPSessionParamsEx2 * params, IDERTout * touts, char * drive0, char * drive1);
+ "IMR_IDERCloseSession": ['uint', ['int']], // IMRResult IMR_IDERCloseSession(ClientID client_id);
+ "IMR_IDERClientFeatureSupported" : ['uint', ['int', _FeaturesSupportedPtr]], // IMRResult IMR_IDERClientFeatureSupported(ClientID client_id, FeaturesSupported * supported);
+ "IMR_IDERGetDeviceState" : ['uint', ['int', _IDERDeviceStatePtr]], // IMRResult IMR_IDERGetDeviceState(ClientID client_id, IDERDeviceState * state);
+ "IMR_IDERSetDeviceState" : ['uint', ['int', _IDERDeviceCmdPtr, _IDERDeviceResultPtr]], // IMRResult IMR_IDERSetDeviceState(ClientID client_id, IDERDeviceCmd * cmd, IDERDeviceResult * result);
+ "IMR_IDERGetSessionStatistics": ['uint', ['int', _IDERStatisticsPtr]], // IMRResult IMR_IDERGetSessionStatistics(ClientID client_id, IDERStatistics * stat);
+ "IMR_SetOpt": ['uint', ['int', 'string', 'string', 'int']], // IMRResult IMR_SetOpt(/*IN*/ClientID id, /*IN*/int optname, /*IN*/ const char *optval, /*IN*/ int optlen);
+ "IMR_GetOpt": ['uint', ['int', 'string', 'pointer', _intPtr]], // IMRResult IMR_GetOpt(/*IN*/ClientID id, /*IN*/int optname, /*OUT*/ char *optval, /*OUT*/ int* optlen);
+ });
+ } catch (e) { return false; }
+ return true;
+ }
+
+ // Try to link to both 32bit and 64bit IMRSDK.dll's
+ if (_Setup('imrsdk') == false) { if (_Setup('imrsdk_x64') == false) { return null; } }
+
+ // IMR_Init
+ obj.Init = function() {
+ var version = new _IMRVersion();
+ var error = _IMRSDK.IMR_Init(version.ref(), "imrsdk.ini");
+ if (error == 4) return _ImrSdkVersion; // If already initialized, return previous version information.
+ if (error != 0) { throw obj.GetErrorString(error); }
+ _ImrSdkVersion = { major: version.major, minor: version.minor };
+ return _ImrSdkVersion;
+ }
+
+ // IMR_InitEx
+ obj.InitEx = function(client) {
+ var version = new _IMRVersion();
+ var callbacks = new _SockCallBacks();
+ callbacks.OpenHandler = OpenHandlerCallBack;
+ callbacks.CloseHandler = CloseHandlerCallBack;
+ callbacks.ReceiveHandler = ReceiveHandlerCallBack;
+ callbacks.SendHandler = SendHandlerCallBack;
+ obj.client = client;
+
+ var error = _IMRSDK.IMR_InitEx(version.ref(), "imrsdk.ini", callbacks.ref());
+ if (error == 4) return _ImrSdkVersion; // If already initialized, return previous version information.
+ if (error != 0) { throw obj.GetErrorString(error); }
+ _ImrSdkVersion = { major: version.major, minor: version.minor };
+ return _ImrSdkVersion;
+ }
+
+ // IMR_ReadyReadSock
+ obj.ReadyReadSock = function (connid, func) { _IMRSDK.IMR_ReadyReadSock.async(connid, func); }
+
+ // IMR_Close
+ obj.Close = function (func) { _IMRSDK.IMR_Close.async(func); }
+
+ // IMR_GetErrorString
+ obj.GetErrorString = function (v) {
+ var errorStringLen = _ref.alloc('int');
+ var error = _IMRSDK.IMR_GetErrorStringLen(v, errorStringLen); if (error != 0) return 'Unknown IMRSDK Error ' + v;
+ var errorStringLenEx = errorStringLen.deref();
+ var errorString = new Buffer(errorStringLenEx);
+ error = _IMRSDK.IMR_GetErrorString(v, errorString); if (error != 0) return 'Unknown IMRSDK Error ' + v;
+ //console.log('IMRSDK ' + errorString.toString().substring(0, errorStringLenEx));
+ return 'IMRSDK ' + errorString.toString().substring(0, errorStringLenEx);
+ }
+
+ // IMR_SetCertificateInfo
+ obj.SetCertificateInfo = function (root_cert, private_cert, cert_pass) {
+ var error = _IMRSDK.IMR_SetCertificateInfo(root_cert, private_cert, cert_pass); if (error != 0) { throw obj.GetErrorString(error); }
+ }
+
+ // IMR_SetClientCertificate
+ obj.SetClientCertificate = function (common_name) {
+ var error = _IMRSDK.IMR_SetClientCertificate(common_name); if (error != 0) { throw obj.GetErrorString(error); }
+ }
+
+ // IMR_AddClient
+ // Type: 1=TCP, 2=TLS
+ obj.AddClient = function (type, ip) {
+ var guid = new Buffer(16);
+ for (var i = 0; i < 16; i++) { guid[i] = Math.floor(Math.random() * 255); }
+ var clientid = _ref.alloc('int');
+ var error = _IMRSDK.IMR_AddClient(type, ip, guid, clientid); if (error != 0) { throw obj.GetErrorString(error); }
+ return clientid.deref();
+ }
+
+ // IMR_RemoveClient
+ obj.RemoveClient = function (client_id) {
+ var error = _IMRSDK.IMR_RemoveClient(client_id); if (error != 0) { throw obj.GetErrorString(error); }
+ }
+
+ // IMR_RemoveAllClients
+ obj.RemoveAllClients = function () {
+ var error = _IMRSDK.IMR_RemoveAllClients(); if (error != 0) { throw obj.GetErrorString(error); }
+ }
+
+ // IMR_GetAllClients
+ obj.GetAllClients = function () {
+ var clientListLength = _ref.alloc('int');
+ var error = _IMRSDK.IMR_GetAllClients(null, clientListLength); if (error != 0) { throw obj.GetErrorString(error); }
+ var clientListLengthEx = clientListLength.deref();
+ var IntArray = _arrayType(_ref.types.int)
+ var buf = new Buffer(4 * clientListLengthEx);
+ var error = _IMRSDK.IMR_GetAllClients(buf, clientListLength); if (error != 0) { throw obj.GetErrorString(error); }
+ clientListLengthEx = clientListLength.deref();
+ var array = IntArray.untilZeros(buf)
+ var clientids = [];
+ for (var i = 0; i < clientListLengthEx; i++) { clientids.push(array[i]); }
+ return clientids;
+ }
+
+ // IMR_GetClientInfo
+ obj.GetClientInfo = function (client_id) {
+ var client = new obj.IMRClientInfo();
+ var error = _IMRSDK.IMR_GetClientInfo(client_id, client.ref()); if (error != 0) { throw obj.GetErrorString(error); }
+ var ip = '', i = 0;
+ while (client.ip[i] != 0) { ip += String.fromCharCode(client.ip[i++]); }
+ return { type: client.type, ip: ip };
+ }
+
+ // IMR_IDEROpenTCPSession
+ obj.IDEROpenTCPSessionAsync = function (client_id, user, pass, driveimg, driveiso, func) {
+ //console.log('IDEROpenTCPSessionAsync', client_id, user, pass, driveimg, driveiso);
+ // Setup parameters
+ var params = new _TCPSessionParams();
+ var user2 = obj.decode_utf8(user);
+ var pass2 = obj.decode_utf8(pass);
+ for (var i = 0; i < 128; i++) { params.user[i] = 0; }
+ for (var i = 0; i < user2.length; i++) { params.user[i] = user2.charCodeAt(i); }
+ for (var i = 0; i < 128; i++) { params.pass[i] = 0; }
+ for (var i = 0; i < pass2.length; i++) { params.pass[i] = pass2.charCodeAt(i); }
+
+ // Setup
+ var IDERTout = new _IDERTout();
+ IDERTout.rx_timeout = 30000; // Default is 10000
+ IDERTout.tx_timeout = 0; // Default is 0
+ IDERTout.hb_timeout = 20000; // Default is 5000
+
+ // Make the call
+ _IMRSDK.IMR_IDEROpenTCPSession.async(client_id, params.ref(), IDERTout.ref(), driveimg, driveiso, function (x, error) {
+ if (error == 38) { return error; } // User consent required
+ //if (error != 0) { throw obj.GetErrorString(error); }
+ if (func != null) { func(error); }
+ });
+ }
+
+ // IMR_IDERCloseSession
+ obj.IDERCloseSessionAsync = function (client_id, func) { _IMRSDK.IMR_IDERCloseSession.async(client_id, func); }
+
+ // IMR_IDERClientFeatureSupported
+ obj.IDERClientFeatureSupported = function (client_id) {
+ var features = new _FeaturesSupported();
+ var error = _IMRSDK.IMR_IDERClientFeatureSupported(client_id, features.ref()); if (error != 0) { throw obj.GetErrorString(error); }
+ return { ider_dev_pri: features.ider_dev_pri, ider_dev_sec: features.ider_dev_sec }
+ }
+
+ // IMR_IDERGetDeviceState
+ obj.IDERGetDeviceState = function (client_id) {
+ var state = new _IDERDeviceState();
+ var error = _IMRSDK.IMR_IDERGetDeviceState(client_id, state.ref()); if (error != 0) { throw obj.GetErrorString(error); }
+ return { pri_default: state.pri_default, pri_current: state.pri_current, sec_default: state.sec_default, sec_current: state.sec_current }
+ }
+
+ // IMR_IDERSetDeviceState Async
+ obj.IDERSetDeviceStateAsync = function (client_id, pri_op, pri_timing, sec_op, sec_timing, func) {
+ var cmd = new _IDERDeviceCmd();
+ cmd.pri_op = pri_op;
+ cmd.pri_timing = pri_timing;
+ cmd.sec_op = sec_op;
+ cmd.sec_timing = sec_timing;
+ var result = new _IDERDeviceResult();
+ _IMRSDK.IMR_IDERSetDeviceState.async(client_id, cmd.ref(), result.ref(), function (x, error) {
+ if (func != null) func(error, { pri_res: result.pri_res, sec_res: result.sec_res });
+ });
+ }
+
+ // IMR_IDERGetSessionStatistics
+ obj.IDERGetSessionStatistics = function (client_id) {
+ var stats = new _IDERStatistics();
+ var error = _IMRSDK.IMR_IDERGetSessionStatistics(client_id, stats.ref()); if (error != 0) { throw obj.GetErrorString(error); }
+ return { error_state: stats.error_state, data_transfer: stats.data_transfer, num_reopen: stats.num_reopen, num_error: stats.num_error, num_reset: stats.num_reset, last_cmd_length: stats.last_cmd_length, data_sent: stats.data_sent, data_received: stats.data_received, packets_sent: stats.packets_sent, packets_received: stats.packets_received };
+ }
+
+ // IMR_SetOpt
+ obj.SetOpt = function (client_id, optname, optval) {
+ var error = _IMRSDK.IMR_SetOpt(client_id, optname, optval, optval.length); if (error != 0) { throw obj.GetErrorString(error); }
+ }
+
+ // IMR_GetOpt
+ obj.GetOpt = function (client_id, optname) {
+ var len = _ref.alloc('int');
+ var error = _IMRSDK.IMR_GetOpt(client_id, optname, null, len); if (error != 0) { throw obj.GetErrorString(error); }
+ var buf = new Buffer(len.deref() + 1);
+ var error = _IMRSDK.IMR_GetOpt(client_id, optname, buf, len); if (error != 0) { throw obj.GetErrorString(error); }
+ // console.log(buf);
+ return buf; // TODO: Return something correct after testing this call
+ }
+
+ // UTF-8 encoding & decoding functions
+ obj.encode_utf8 = function (s) { return unescape(encodeURIComponent(s)); }
+ obj.decode_utf8 = function (s) { return decodeURIComponent(escape(s)); }
+
+ return obj;
+}
+
+globalIderPendingCalls = 0;
+
+// Construct a Intel AMT IDER object
+var CreateAmtRemoteIderIMR = function () {
+ if (globalIderPendingCalls != 0) { console.log('Incomplete IDER cleanup (' + globalIderPendingCalls + ').'); return null; } // IDER is not ready.
+ var _net = require('net');
+ var _tls = require('tls');
+
+ var obj = {};
+ obj.onStateChanged = null;
+ obj.state = 0;
+
+ obj.m = {};
+ obj.m.protocol = 3; // IDER
+ obj.m.state = 0;
+ obj.m.bytesToAmt = 0;
+ obj.m.bytesFromAmt = 0;
+ obj.m.imrsdk = null;
+ obj.receivedCount = 0;
+
+ // Private method
+ obj.StateChange = function (newstate) { if (obj.state != newstate) { obj.state = newstate; obj.onStateChanged(obj, obj.state); } }
+
+ obj.m.Start = function (host, port, user, pass, tls, wsmanCert, tlsOptions) {
+ obj.constants = require('constants');
+ obj.m.host = host;
+ obj.m.port = port;
+ obj.m.user = user;
+ obj.m.pass = pass;
+ obj.m.tls = tls;
+ obj.m.xtlsoptions = tlsOptions;
+ obj.m.wsmanCert = wsmanCert;
+ obj.m.bytesToAmt = 0;
+ obj.m.bytesFromAmt = 0;
+
+ if (obj.m.onDialogPrompt) {
+ if (require('os').platform() == 'win32') {
+ obj.m.onDialogPrompt(obj.m, { 'html': ' Select a CDROM and Floppy disk image to start the disk redirection.ISO & IMG from file ISO from drive, IMG from file ISO from file, IMG from drive ISO & IMG from drive Source
On Reset Gracefully Immediately Start
' });
+ } else {
+ obj.m.onDialogPrompt(obj.m, { 'html': ' Select a CDROM and Floppy disk image to start the disk redirection.On Reset Gracefully Immediately Start
' });
+ }
+ }
+ }
+
+ obj.m.Stop = function () {
+ if (obj.m.client != null) {
+ //console.log('obj.m.Stop - client');
+ try { obj.m.client.destroy(); } catch (e) { console.log(e); }
+ delete obj.m.client;
+ }
+ if (obj.m.imrsdk) {
+ //console.log('obj.m.Stop - imrsdk', obj.m.clientid);
+ try
+ {
+ if (obj.m.clientid !== undefined) {
+ try { obj.m.imrsdk.IDERCloseSessionAsync(obj.m.clientid, function (error) { }); } catch (e) { }
+ delete obj.m.clientid;
+ }
+ obj.m.imrsdk.Close(function (error) { });
+ } catch (e) { }
+ delete obj.m.imrsdk;
+ }
+ obj.StateChange(0);
+ }
+
+ obj.m.Update = function () {
+ if ((obj.m.imrsdk != undefined) && (obj.m.clientid !== undefined)) {
+ try {
+ var stats = obj.m.imrsdk.IDERGetSessionStatistics(obj.m.clientid);
+ obj.m.bytesToAmt = stats.data_sent;
+ obj.m.bytesFromAmt = stats.data_received;
+ } catch (e) {
+ obj.m.bytesToAmt = -1;
+ obj.m.bytesFromAmt = -1;
+ }
+ } else {
+ obj.m.bytesToAmt = 0;
+ obj.m.bytesFromAmt = 0;
+ }
+ }
+
+ obj.m.dialogPrompt = function (userConsentFunc) {
+ try {
+ obj.m.Stop();
+ if (Q('storageserveroption')) {
+ var sel = 0;
+ if (require('os').platform() == 'win32') { sel = Q('storagesourceoption').value; }
+ if ((sel & 1) == 0) {
+ var x = Q('iderisofile');
+ if (!x || x.files.length != 1) { obj.m.isopath = 'empty.iso'; } else { obj.m.isopath = x.files[0].path; }
+ } else {
+ obj.m.isopath = Q('iderisodrive').value;
+ }
+ if ((sel & 2) == 0) {
+ var x = Q('iderimgfile');
+ if (!x || x.files.length != 1) { obj.m.imgpath = 'empty.img'; } else { obj.m.imgpath = x.files[0].path; }
+ } else {
+ obj.m.imgpath = Q('iderimgdrive').value;
+ }
+ obj.m.startoption = Q('storageserveroption').value;
+ startIderSession(userConsentFunc);
+ }
+ } catch (e) {
+ //console.log(e);
+ obj.m.onDialogPrompt(obj.m, { 'html': e }, 1);
+ }
+ }
+
+ function startIderSession(userConsentFunc) {
+ if (globalIderPendingCalls != 0) { console.log('Incomplete IDER cleanup (' + globalIderPendingCalls + ').'); return; }
+ try {
+ //console.log("IDER-Start");
+ if (obj.m.xtlsoptions && obj.m.xtlsoptions.meshServerConnect) {
+ // Open thru MeshCentral websocket wrapper
+ obj.m.client = CreateWebSocketWrapper(obj.m.xtlsoptions.host, obj.m.xtlsoptions.port, '/webrelay.ashx?user=' + encodeURIComponent(obj.m.xtlsoptions.username) + '&pass=' + encodeURIComponent(obj.m.xtlsoptions.password) + '&host=' + encodeURIComponent(obj.m.host) + '&p=2', obj.m.xtlsoptions.xtlsFingerprint);
+ obj.m.client.connect(function () {
+ //console.log('IDER Connected WS, ' + obj.m.xtlsoptions.host + ':' + obj.m.xtlsoptions.port + ' to ' + obj.m.host);
+ startIderSessionEx(userConsentFunc);
+ });
+ } else if (obj.m.tls == 0) {
+ // Open connection without TLS
+ obj.m.client = new _net.Socket();
+ obj.m.client.connect(obj.m.port, obj.m.host, function () {
+ //console.log('IDER Connected TCP, ' + obj.m.host + ':' + obj.m.port);
+ startIderSessionEx(userConsentFunc);
+ });
+ } else {
+ // Open connection with TLS
+ if (obj.m.xtlsoptions == null) { obj.m.xtlsoptions = { secureProtocol: 'TLSv1_method', ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: obj.constants.SSL_OP_NO_SSLv2 | obj.constants.SSL_OP_NO_SSLv3 | obj.constants.SSL_OP_NO_COMPRESSION | obj.constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false }; }
+ obj.m.client = _tls.connect(obj.m.port, obj.m.host, obj.m.xtlsoptions, function () {
+ //console.log('IDER Connected TLS, ' + obj.m.host + ':' + obj.m.port);
+
+ // Check the Intel AMT certificate, it must be the same as the one used for WSMAN. If not, disconnect.
+ var iderTlsCertificate = obj.m.client.getPeerCertificate();
+ if ((iderTlsCertificate == null) || (obj.m.wsmanCert == null) || (iderTlsCertificate.fingerprint != obj.m.wsmanCert.fingerprint)) {
+ console.log("Invalid IDER certificate, disconnecting.", iderTlsCertificate);
+ obj.m.Stop();
+ } else {
+ startIderSessionEx(userConsentFunc)
+ }
+ });
+ }
+
+ obj.m.client.setEncoding('binary');
+
+ obj.m.client.on('data', function (data) {
+ //console.log("IDER-RECV(" + data.length + ", " + obj.receivedCount + "): " + rstr2hex(data));
+
+ if (obj.m.imrsdk == null) { return; }
+
+ if ((obj.receivedCount == 0) && (data.charCodeAt(0) == 0x11) && (data.charCodeAt(1) == 0x05)) {
+ // We got a user consent error, handle it now before IMRSDK.dll can get it.
+ console.log('IDER user consent required.');
+ obj.m.imrsdk.pendingData[obj.m.clientid] = String.fromCharCode(0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); // Try to cause a fault.
+ obj.m.imrsdk.ReadyReadSock(0, function (x, error) { });
+ setTimeout(function () { obj.m.userConsentFunc(startIderSession); }, 500);
+ } else {
+ if (obj.m.imrsdk.pendingData[obj.m.clientid] == null) { obj.m.imrsdk.pendingData[obj.m.clientid] = data; } else { obj.m.imrsdk.pendingData[obj.m.clientid] += data; }
+ obj.m.imrsdk.ReadyReadSock(0, function (x, error) { });
+ }
+ obj.receivedCount += data.length;
+ });
+
+ obj.m.client.on('close', function () { obj.m.Stop(); });
+
+ // If the TCP connection causes an error, disconnect the associated web socket.
+ obj.m.client.on('error', function (err) { obj.m.Stop(); });
+ } catch (e) {
+ //console.log(e);
+ obj.m.Stop();
+ obj.m.onDialogPrompt(obj.m, { 'html': e }, 1);
+ }
+ }
+
+ function startIderSessionEx(userConsentFunc) {
+ try {
+ //console.log("IDER-StartEx");
+ obj.m.userConsentFunc = userConsentFunc;
+ obj.m.imrsdk = CreateIMRSDKWrapper();
+ obj.m.imrsdk.InitEx(obj.m.client);
+ obj.m.imrsdk.RemoveAllClients();
+ if (obj.m.amtcertpath) { obj.m.imrsdk.SetCertificateInfo(obj.m.amtcertpath, null, null); }
+ obj.m.clientid = obj.m.imrsdk.AddClient(obj.m.tls + 1, obj.m.host);
+ globalIderPendingCalls++;
+ //console.log('IDEROpenTCPSessionAsync-call');
+ var error = obj.m.imrsdk.IDEROpenTCPSessionAsync(obj.m.clientid, obj.m.user, obj.m.pass, obj.m.imgpath, obj.m.isopath, function (error) {
+ //console.log('IDEROpenTCPSessionAsync-callback(' + error + ')');
+ globalIderPendingCalls--;
+ if (obj.m.imrsdk == null) return; // We closed already, exit now.
+ if ((error == 38) && (userConsentFunc != undefined)) { obj.m.Stop(); userConsentFunc(startIderSession); return; }
+ if (error != 0) { console.log('IDER error ' + error); obj.m.Stop(); }
+ if (error == 0) {
+ globalIderPendingCalls++;
+ obj.m.imrsdk.IDERSetDeviceStateAsync(obj.m.clientid, 0, obj.m.startoption, 0, obj.m.startoption, function (error, result) {
+ globalIderPendingCalls--;
+ if (error != 0) {
+ obj.m.Stop();
+ obj.m.onDialogPrompt(obj.m, { 'html': e }, 1);
+ } else {
+ obj.StateChange(3);
+ }
+ });
+ }
+ });
+ } catch (e) {
+ //console.log(e);
+ obj.m.Stop();
+ obj.m.onDialogPrompt(obj.m, { 'html': e }, 1);
+ }
+ }
+
+ return obj;
+}
diff --git a/amt-ider-server-ws-0.0.1.js b/amt-ider-server-ws-0.0.1.js
new file mode 100644
index 0000000..d2ff62e
--- /dev/null
+++ b/amt-ider-server-ws-0.0.1.js
@@ -0,0 +1,100 @@
+/**
+* @description IDER Handling Module
+* @author Ylian Saint-Hilaire
+* @version v0.0.2
+*/
+
+// Construct a Intel AMT Server IDER object
+var CreateAmtRemoteServerIder = function () {
+ var obj = {};
+ obj.protocol = 4; // IDER-Server
+
+ obj.iderStart = 0; // OnReboot = 0, Graceful = 1, Now = 2
+ obj.floppy = null;
+ obj.cdrom = null;
+ obj.state = 0;
+ obj.onStateChanged = null;
+ obj.m = {
+ sectorStats: null,
+ onDialogPrompt: null,
+ dialogPrompt: function (data) { obj.socket.send(JSON.stringify({ action: 'dialogResponse', args: data })); },
+ bytesToAmt: 0,
+ bytesFromAmt: 0,
+ server: true,
+ Stop: function () { obj.Stop(); }
+ };
+
+ // Private method
+ function debug() { if (urlvars && urlvars['idertrace']) { console.log(...arguments); } }
+
+ // Private method, called by parent when it change state
+ obj.xxStateChange = function (newstate) {
+ if (obj.state == newstate) return;
+ debug("SIDER-StateChange", newstate);
+ obj.state = newstate;
+ if (obj.onStateChanged != null) { obj.onStateChanged(obj, obj.state); }
+ }
+
+ obj.Start = function (host, port, user, pass, tls) {
+ debug("SIDER-Start", host, port, user, pass, tls);
+ obj.host = host;
+ obj.port = port;
+ obj.user = user;
+ obj.pass = pass;
+ obj.connectstate = 0;
+ obj.socket = new WebSocket(window.location.protocol.replace("http", "ws") + "//" + window.location.host + window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) + "/webider.ashx?host=" + host + "&port=" + port + "&tls=" + tls + ((user == '*') ? "&serverauth=1" : "") + ((typeof pass === "undefined") ? ("&serverauth=1&user=" + user) : "") + "&tls1only=" + obj.tlsv1only);
+ obj.socket.onopen = obj.xxOnSocketConnected;
+ obj.socket.onmessage = obj.xxOnMessage;
+ obj.socket.onclose = obj.xxOnSocketClosed;
+ obj.xxStateChange(1);
+ }
+
+ obj.Stop = function () {
+ debug("SIDER-Stop");
+ if (obj.socket != null) { obj.socket.close(); obj.socket = null; }
+ obj.xxStateChange(0);
+ }
+
+ obj.xxOnSocketConnected = function () {
+ obj.xxStateChange(2);
+ obj.socket.send(JSON.stringify({ action: 'start' }));
+ }
+
+ obj.xxOnMessage = function (data) {
+ var msg = null;
+ try { msg = JSON.parse(data.data); } catch (ex) { }
+ if ((msg == null) || (typeof msg.action != 'string')) return;
+
+ switch (msg.action) {
+ case 'dialog': {
+ if (obj.m.onDialogPrompt != null) { obj.m.onDialogPrompt(obj, msg.args, msg.buttons); }
+ break;
+ }
+ case 'state': {
+ if (msg.state == 2) { obj.xxStateChange(3); }
+ break;
+ }
+ case 'stats': {
+ obj.m.bytesToAmt = msg.toAmt;
+ obj.m.bytesFromAmt = msg.fromAmt;
+ if (obj.m.sectorStats) { obj.m.sectorStats(msg.mode, msg.dev, msg.total, msg.start, msg.len); }
+ break;
+ }
+ case 'error': {
+ var iderErrorStrings = ["", "Floppy disk image does not exist", "Invalid floppy disk image", "Unable to open floppy disk image", "CDROM disk image does not exist", "Invalid CDROM disk image", "Unable to open CDROM disk image", "Can't perform IDER with no disk images"];
+ console.log('IDER Error: ' + iderErrorStrings[msg.code]);
+ // TODO: Display dialog box this error.
+ break;
+ }
+ default: {
+ console.log('Unknown Server IDER action: ' + msg.action);
+ breal;
+ }
+ }
+
+ }
+
+ obj.xxOnSocketClosed = function () { obj.Stop(); }
+
+ return obj;
+}
diff --git a/amt-ider-ws-0.0.1.js b/amt-ider-ws-0.0.1.js
new file mode 100644
index 0000000..77084ae
--- /dev/null
+++ b/amt-ider-ws-0.0.1.js
@@ -0,0 +1,692 @@
+/**
+* @description IDER Handling Module
+* @author Ylian Saint-Hilaire
+* @version v0.0.2
+*/
+
+// Construct a Intel AMT IDER object
+var CreateAmtRemoteIder = function () {
+ var obj = {};
+ obj.protocol = 3; // IDER
+ obj.bytesToAmt = 0;
+ obj.bytesFromAmt = 0;
+ obj.rx_timeout = 30000; // Default 30000
+ obj.tx_timeout = 0; // Default 0
+ obj.heartbeat = 20000; // Default 20000
+ obj.version = 1;
+ obj.acc = "";
+ obj.inSequence = 0;
+ obj.outSequence = 0;
+ obj.iderinfo = null;
+ obj.enabled = false;
+ obj.iderStart = 0; // OnReboot = 0, Graceful = 1, Now = 2
+ obj.floppy = null;
+ obj.cdrom = null;
+ obj.floppyReady = false;
+ obj.cdromReady = false;
+ //obj.pingTimer = null;
+ // ###BEGIN###{IDERStats}
+ obj.sectorStats = null;
+ // ###END###{IDERStats}
+
+ // Private method
+ // ###BEGIN###{IDERDebug}
+ function debug() { if (urlvars && urlvars['idertrace']) { console.log(...arguments); } }
+ // ###END###{IDERDebug}
+
+ // Mode Sense
+ var IDE_ModeSence_LS120Disk_Page_Array = String.fromCharCode(0x00, 0x26, 0x31, 0x80, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1E, 0x10, 0xA9, 0x08, 0x20, 0x02, 0x00, 0x03, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xD0, 0x00, 0x00);
+ var IDE_ModeSence_3F_LS120_Array = String.fromCharCode(0x00, 0x5c, 0x24, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x16, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x05, 0x1E, 0x10, 0xA9, 0x08, 0x20, 0x02, 0x00, 0x03, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xD0, 0x00, 0x00, 0x08, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x11, 0x24, 0x31);
+ var IDE_ModeSence_FloppyDisk_Page_Array = String.fromCharCode(0x00, 0x26, 0x24, 0x80, 0x00, 0x00, 0x00, 0x00, 0x05, 0x1E, 0x04, 0xB0, 0x02, 0x12, 0x02, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xD0, 0x00, 0x00);
+ var IDE_ModeSence_3F_Floppy_Array = String.fromCharCode(0x00, 0x5c, 0x24, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x16, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x05, 0x1e, 0x04, 0xb0, 0x02, 0x12, 0x02, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xd0, 0x00, 0x00, 0x08, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x11, 0x24, 0x31);
+ var IDE_ModeSence_CD_1A_Array = String.fromCharCode(0x00, 0x12, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+ //var IDE_ModeSence_CD_1B_Array = String.fromCharCode(0x00, 0x12, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1B, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+ var IDE_ModeSence_CD_1D_Array = String.fromCharCode(0x00, 0x12, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+ var IDE_ModeSence_CD_2A_Array = String.fromCharCode(0x00, 0x20, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x18, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+ //var IDE_ModeSence_CD_01_Array = String.fromCharCode(0x00, 0x0E, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00);
+ var IDE_ModeSence_3F_CD_Array = String.fromCharCode(0x00, 0x28, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x18, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+
+ // 0x46 constant data
+ var IDE_CD_ConfigArrayHeader = String.fromCharCode(0x00, 0x00,0x00, 0x28, 0x00, 0x00, 0x00, 0x08);
+ var IDE_CD_ConfigArrayProfileList = String.fromCharCode(0x00, 0x00, 0x03, 0x04, 0x00, 0x08, 0x01, 0x00);
+ var IDE_CD_ConfigArrayCore = String.fromCharCode(0x00, 0x01, 0x03, 0x04, 0x00, 0x00, 0x00, 0x02);
+ var IDE_CD_Morphing = String.fromCharCode(0x00, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00);
+ var IDE_CD_ConfigArrayRemovable = String.fromCharCode(0x00, 0x03, 0x03, 0x04, 0x29, 0x00, 0x00, 0x02);
+ var IDE_CD_ConfigArrayRandom = String.fromCharCode(0x00, 0x10, 0x01, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00);
+ var IDE_CD_Read = String.fromCharCode(0x00, 0x1E, 0x03, 0x00);
+ var IDE_CD_PowerManagement = String.fromCharCode(0x01, 0x00, 0x03, 0x00);
+ var IDE_CD_Timeout = String.fromCharCode(0x01, 0x05, 0x03, 0x00);
+
+ // 0x01 constant data
+ var IDE_ModeSence_FloppyError_Recovery_Array = String.fromCharCode(0x00, 0x12, 0x24, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00);
+ var IDE_ModeSence_Ls120Error_Recovery_Array = String.fromCharCode(0x00, 0x12, 0x31, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00);
+ var IDE_ModeSence_CDError_Recovery_Array = String.fromCharCode(0x00, 0x0E, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00);
+
+
+ // Private method, called by parent when it change state
+ obj.xxStateChange = function (newstate) {
+ // ###BEGIN###{IDERDebug}
+ debug("IDER-StateChange", newstate);
+ // ###END###{IDERDebug}
+ if (newstate == 0) { obj.Stop(); }
+ if (newstate == 3) { obj.Start(); }
+ }
+
+ obj.Start = function () {
+ // ###BEGIN###{IDERDebug}
+ debug("IDER-Start");
+ debug(obj.floppy, obj.cdrom);
+ // ###END###{IDERDebug}
+ obj.bytesToAmt = 0;
+ obj.bytesFromAmt = 0;
+ obj.inSequence = 0;
+ obj.outSequence = 0;
+ g_readQueue = [];
+
+ // Send first command, OPEN_SESSION
+ obj.SendCommand(0x40, ShortToStrX(obj.rx_timeout) + ShortToStrX(obj.tx_timeout) + ShortToStrX(obj.heartbeat) + IntToStrX(obj.version));
+
+ // Send sector stats
+ // ###BEGIN###{IDERStats}
+ if (obj.sectorStats) {
+ obj.sectorStats(0, 0, obj.floppy?(obj.floppy.size >> 9):0);
+ obj.sectorStats(0, 1, obj.cdrom ? (obj.cdrom.size >> 11) : 0);
+ }
+ // ###END###{IDERStats}
+
+ // Setup the ping timer
+ //obj.pingTimer = setInterval(function () { obj.SendCommand(0x44); }, 5000);
+ }
+
+ obj.Stop = function () {
+ // ###BEGIN###{IDERDebug}
+ debug("IDER-Stop");
+ // ###END###{IDERDebug}
+ //if (obj.pingTimer) { clearInterval(obj.pingTimer); obj.pingTimer = null; }
+ obj.parent.Stop();
+ }
+
+ // Private method
+ obj.ProcessData = function (data) {
+ obj.bytesFromAmt += data.length;
+ obj.acc += data;
+ // ###BEGIN###{IDERDebug}
+ debug('IDER-ProcessData', obj.acc.length, rstr2hex(obj.acc));
+ // ###END###{IDERDebug}
+
+ // Process as many commands as possible
+ while (true) {
+ var len = obj.ProcessDataEx();
+ if (len == 0) return;
+ if (obj.inSequence != ReadIntX(obj.acc, 4)) {
+ // ###BEGIN###{IDERDebug}
+ debug('ERROR: Out of sequence', obj.inSequence, ReadIntX(obj.acc, 4));
+ // ###END###{IDERDebug}
+ obj.Stop();
+ return;
+ }
+ obj.inSequence++;
+ obj.acc = obj.acc.substring(len);
+ }
+ }
+
+ // Private method
+ obj.SendCommand = function (cmdid, data, completed, dma) {
+ if (data == null) { data = ''; }
+ var attributes = ((cmdid > 50) && (completed == true)) ? 2 : 0;
+ if (dma) { attributes += 1; }
+ var x = String.fromCharCode(cmdid, 0, 0, attributes) + IntToStrX(obj.outSequence++) + data;
+ obj.parent.xxSend(x);
+ obj.bytesToAmt += x.length;
+ // ###BEGIN###{IDERDebug}
+ if (cmdid != 0x4B) { debug('IDER-SendData', x.length, rstr2hex(x)); }
+ // ###END###{IDERDebug}
+ }
+
+ // CommandEndResponse (SCSI_SENSE)
+ obj.SendCommandEndResponse = function (error, sense, device, asc, asq) {
+ if (error) { obj.SendCommand(0x51, String.fromCharCode(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xc5, 0, 3, 0, 0, 0, device, 0x50, 0, 0, 0), true); }
+ else { obj.SendCommand(0x51, String.fromCharCode(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x87, (sense << 4), 3, 0, 0, 0, device, 0x51, sense, asc, asq), true); }
+ }
+
+ // DataToHost (SCSI_READ)
+ obj.SendDataToHost = function (device, completed, data, dma) {
+ var dmalen = (dma) ? 0 : data.length;
+ if (completed == true) {
+ obj.SendCommand(0x54, String.fromCharCode(0, (data.length & 0xff), (data.length >> 8), 0, dma ? 0xb4 : 0xb5, 0, 2, 0, (dmalen & 0xff), (dmalen >> 8), device, 0x58, 0x85, 0, 3, 0, 0, 0, device, 0x50, 0, 0, 0, 0, 0, 0) + data, completed, dma);
+ } else {
+ obj.SendCommand(0x54, String.fromCharCode(0, (data.length & 0xff), (data.length >> 8), 0, dma ? 0xb4 : 0xb5, 0, 2, 0, (dmalen & 0xff), (dmalen >> 8), device, 0x58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + data, completed, dma);
+ }
+ }
+
+ // GetDataFromHost (SCSI_CHUNK)
+ obj.SendGetDataFromHost = function (device, chunksize) {
+ obj.SendCommand(0x52, String.fromCharCode(0, (chunksize & 0xff), (chunksize >> 8), 0, 0xb5, 0, 0, 0, (chunksize & 0xff), (chunksize >> 8), device, 0x58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), false);
+ }
+
+ // DisableEnableFeatures (STATUS_DATA)
+ // If type is REGS_TOGGLE (3), 4 bytes of data must be provided.
+ obj.SendDisableEnableFeatures = function (type, data) { if (data == null) { data = ''; } obj.SendCommand(0x48, String.fromCharCode(type) + data); }
+
+ // Private method
+ obj.ProcessDataEx = function () {
+ if (obj.acc.length < 8) return 0;
+
+ // First 8 bytes are the header
+ // CommandID + 0x000000 + Sequence Number
+
+ switch(obj.acc.charCodeAt(0)) {
+ case 0x41: // OPEN_SESSION
+ if (obj.acc.length < 30) return 0;
+ var len = obj.acc.charCodeAt(29);
+ if (obj.acc.length < (30 + len)) return 0;
+ obj.iderinfo = {};
+ obj.iderinfo.major = obj.acc.charCodeAt(8);
+ obj.iderinfo.minor = obj.acc.charCodeAt(9);
+ obj.iderinfo.fwmajor = obj.acc.charCodeAt(10);
+ obj.iderinfo.fwminor = obj.acc.charCodeAt(11);
+ obj.iderinfo.readbfr = ReadShortX(obj.acc, 16);
+ obj.iderinfo.writebfr = ReadShortX(obj.acc, 18);
+ obj.iderinfo.proto = obj.acc.charCodeAt(21);
+ obj.iderinfo.iana = ReadIntX(obj.acc, 25);
+ // ###BEGIN###{IDERDebug}
+ debug(obj.iderinfo);
+ // ###END###{IDERDebug}
+
+ if (obj.iderinfo.proto != 0) {
+ // ###BEGIN###{IDERDebug}
+ debug("Unknown proto", obj.iderinfo.proto);
+ // ###END###{IDERDebug}
+ obj.Stop();
+ }
+ if (obj.iderinfo.readbfr > 8192) {
+ // ###BEGIN###{IDERDebug}
+ debug("Illegal read buffer size", obj.iderinfo.readbfr);
+ // ###END###{IDERDebug}
+ obj.Stop();
+ }
+ if (obj.iderinfo.writebfr > 8192) {
+ // ###BEGIN###{IDERDebug}
+ debug("Illegal write buffer size", obj.iderinfo.writebfr);
+ // ###END###{IDERDebug}
+ obj.Stop();
+ }
+
+ if (obj.iderStart == 0) { obj.SendDisableEnableFeatures(3, IntToStrX(0x01 + 0x08)); } // OnReboot
+ else if (obj.iderStart == 1) { obj.SendDisableEnableFeatures(3, IntToStrX(0x01 + 0x10)); } // Graceful
+ else if (obj.iderStart == 2) { obj.SendDisableEnableFeatures(3, IntToStrX(0x01 + 0x18)); } // Now
+ //obj.SendDisableEnableFeatures(1); // GetSupportedFeatures
+ return 30 + len;
+ case 0x43: // CLOSE
+ // ###BEGIN###{IDERDebug}
+ debug('CLOSE');
+ // ###END###{IDERDebug}
+ obj.Stop();
+ return 8;
+ case 0x44: // KEEPALIVEPING
+ obj.SendCommand(0x45); // Send PONG back
+ return 8;
+ case 0x45: // KEEPALIVEPONG
+ // ###BEGIN###{IDERDebug}
+ debug('PONG');
+ // ###END###{IDERDebug}
+ return 8;
+ case 0x46: // RESETOCCURED
+ if (obj.acc.length < 9) return 0;
+ var resetMask = obj.acc.charCodeAt(8);
+ if (g_media === null) {
+ // No operations are pending
+ obj.SendCommand(0x47); // Send ResetOccuredResponse
+ // ###BEGIN###{IDERDebug}
+ debug('RESETOCCURED1', resetMask);
+ // ###END###{IDERDebug}
+ } else {
+ // Operations are being done, sent the reset once completed.
+ g_reset = true;
+ // ###BEGIN###{IDERDebug}
+ debug('RESETOCCURED2', resetMask);
+ // ###END###{IDERDebug}
+ }
+ return 9;
+ case 0x49: // STATUS_DATA - DisableEnableFeaturesReply
+ if (obj.acc.length < 13) return 0;
+ var type = obj.acc.charCodeAt(8);
+ var value = ReadIntX(obj.acc, 9);
+ // ###BEGIN###{IDERDebug}
+ debug('STATUS_DATA', type, value);
+ // ###END###{IDERDebug}
+ switch (type)
+ {
+ case 1: // REGS_AVAIL
+ if (value & 1) {
+ if (obj.iderStart == 0) { obj.SendDisableEnableFeatures(3, IntToStrX(0x01 + 0x08)); } // OnReboot
+ else if (obj.iderStart == 1) { obj.SendDisableEnableFeatures(3, IntToStrX(0x01 + 0x10)); } // Graceful
+ else if (obj.iderStart == 2) { obj.SendDisableEnableFeatures(3, IntToStrX(0x01 + 0x18)); } // Now
+ }
+ break;
+ case 2: // REGS_STATUS
+ obj.enabled = (value & 2) ? true : false;
+ // ###BEGIN###{IDERDebug}
+ debug("IDER Status: " + obj.enabled);
+ // ###END###{IDERDebug}
+ break;
+ case 3: // REGS_TOGGLE
+ if (value != 1) {
+ // ###BEGIN###{IDERDebug}
+ debug("Register toggle failure");
+ // ###END###{IDERDebug}
+ } //else { obj.SendDisableEnableFeatures(2); }
+ break;
+ }
+ return 13;
+ case 0x4A: // ERROR OCCURED
+ if (obj.acc.length < 11) return 0;
+ // ###BEGIN###{IDERDebug}
+ debug('IDER: ABORT', obj.acc.charCodeAt(8));
+ // ###END###{IDERDebug}
+ //obj.Stop();
+ return 11;
+ case 0x4B: // HEARTBEAT
+ // ###BEGIN###{IDERDebug}
+ //debug('HEARTBEAT');
+ // ###END###{IDERDebug}
+ return 8;
+ case 0x50: // COMMAND WRITTEN
+ if (obj.acc.length < 28) return 0;
+ var device = (obj.acc.charCodeAt(14) & 0x10) ? 0xB0 : 0xA0;
+ var deviceFlags = obj.acc.charCodeAt(14);
+ var cdb = obj.acc.substring(16, 28);
+ var featureRegister = obj.acc.charCodeAt(9);
+ // ###BEGIN###{IDERDebug}
+ debug('SCSI_CMD', device, rstr2hex(cdb), featureRegister, deviceFlags);
+ // ###END###{IDERDebug}
+ handleSCSI(device, cdb, featureRegister, deviceFlags);
+ return 28;
+ case 0x53: // DATA FROM HOST
+ if (obj.acc.length < 14) return 0;
+ var len = ReadShortX(obj.acc, 9);
+ if (obj.acc.length < (14 + len)) return 0;
+ // ###BEGIN###{IDERDebug}
+ debug('SCSI_WRITE, len = ' + (14 + len));
+ // ###END###{IDERDebug}
+ obj.SendCommand(0x51, String.fromCharCode(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x70, 0x03, 0x00, 0x00, 0x00, 0xa0, 0x51, 0x07, 0x27, 0x00), true);
+ return 14 + len;
+ default:
+ // ###BEGIN###{IDERDebug}
+ debug('Unknown IDER command', obj.acc[0]);
+ // ###END###{IDERDebug}
+ obj.Stop();
+ break;
+ }
+ return 0;
+ }
+
+ function handleSCSI(dev, cdb, featureRegister, deviceFlags)
+ {
+ var lba;
+ var len;
+
+ switch(cdb.charCodeAt(0))
+ {
+ case 0x00: // TEST_UNIT_READY:
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI: TEST_UNIT_READY", dev);
+ // ###END###{IDERDebug}
+ switch (dev) {
+ case 0xA0: // DEV_FLOPPY
+ if (obj.floppy == null) { obj.SendCommandEndResponse(1, 0x02, dev, 0x3a, 0x00); return -1; }
+ if (obj.floppyReady == false) { obj.floppyReady = true; obj.SendCommandEndResponse(1, 0x06, dev, 0x28, 0x00); return -1; } // Switch to ready
+ break;
+ case 0xB0: // DEV_CDDVD
+ if (obj.cdrom == null) { obj.SendCommandEndResponse(1, 0x02, dev, 0x3a, 0x00); return -1; }
+ if (obj.cdromReady == false) { obj.cdromReady = true; obj.SendCommandEndResponse(1, 0x06, dev, 0x28, 0x00); return -1; } // Switch to ready
+ break;
+ default:
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI Internal error 3", dev);
+ // ###END###{IDERDebug}
+ return -1;
+ }
+ obj.SendCommandEndResponse(1, 0x00, dev, 0x00, 0x00); // Indicate ready
+ break;
+ case 0x08: // READ_6
+ lba = ((cdb.charCodeAt(1) & 0x1f) << 16) + (cdb.charCodeAt(2) << 8) + cdb.charCodeAt(3);
+ len = cdb.charCodeAt(4);
+ if (len == 0) { len = 256; }
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI: READ_6", dev, lba, len);
+ // ###END###{IDERDebug}
+ sendDiskData(dev, lba, len, featureRegister);
+ break;
+ case 0x0a: // WRITE_6
+ lba = ((cdb.charCodeAt(1) & 0x1f) << 16) + (cdb.charCodeAt(2) << 8) + cdb.charCodeAt(3);
+ len = cdb.charCodeAt(4);
+ if (len == 0) { len = 256; }
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI: WRITE_6", dev, lba, len);
+ // ###END###{IDERDebug}
+ obj.SendCommandEndResponse(1, 0x02, dev, 0x3a, 0x00); // Write is not supported, remote no medium.
+ return -1;
+ /*
+ case 0x15: // MODE_SELECT_6:
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI ERROR: MODE_SELECT_6", dev);
+ // ###END###{IDERDebug}
+ obj.SendCommandEndResponse(1, 0x05, dev, 0x20, 0x00);
+ return -1;
+ */
+ case 0x1a: // MODE_SENSE_6
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI: MODE_SENSE_6", dev);
+ // ###END###{IDERDebug}
+ if ((cdb.charCodeAt(2) == 0x3f) && (cdb.charCodeAt(3) == 0x00)) {
+ var a = 0, b = 0;
+ switch (dev) {
+ case 0xA0: // DEV_FLOPPY
+ if (obj.floppy == null) { obj.SendCommandEndResponse(1, 0x02, dev, 0x3a, 0x00); return -1; }
+ a = 0x00;
+ b = 0x80; // Read only = 0x80, Read write = 0x00
+ break;
+ case 0xB0: // DEV_CDDVD
+ if (obj.cdrom == null) { obj.SendCommandEndResponse(1, 0x02, dev, 0x3a, 0x00); return -1; }
+ a = 0x05;
+ b = 0x80;
+ break;
+ default:
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI Internal error 6", dev);
+ // ###END###{IDERDebug}
+ return -1;
+ }
+ obj.SendDataToHost(dev, true, String.fromCharCode(0, a, b, 0), featureRegister & 1);
+ return;
+ }
+ obj.SendCommandEndResponse(1, 0x05, dev, 0x24, 0x00);
+ break;
+ case 0x1b: // START_STOP (Called when you eject the CDROM)
+ //var immediate = cdb.charCodeAt(1) & 0x01;
+ //var loej = cdb.charCodeAt(4) & 0x02;
+ //var start = cdb.charCodeAt(4) & 0x01;
+ obj.SendCommandEndResponse(1, 0, dev);
+ break;
+ case 0x1e: // LOCK_UNLOCK - ALLOW_MEDIUM_REMOVAL
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI: ALLOW_MEDIUM_REMOVAL", dev);
+ // ###END###{IDERDebug}
+ if ((dev == 0xA0) && (obj.floppy == null)) { obj.SendCommandEndResponse(1, 0x02, dev, 0x3a, 0x00); return -1; }
+ if ((dev == 0xB0) && (obj.cdrom == null)) { obj.SendCommandEndResponse(1, 0x02, dev, 0x3a, 0x00); return -1; }
+ obj.SendCommandEndResponse(1, 0x00, dev, 0x00, 0x00);
+ break;
+ case 0x23: // READ_FORMAT_CAPACITIES (Floppy only)
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI: READ_FORMAT_CAPACITIES", dev);
+ // ###END###{IDERDebug}
+ var buflen = ReadShort(cdb, 7);
+ var mediaStatus = 0, sectors;
+ var mcSize = buflen / 8; // Capacity descriptor size is 8
+
+ switch (dev) {
+ case 0xA0: // DEV_FLOPPY
+ if ((obj.floppy == null) || (obj.floppy.size == 0)) { obj.SendCommandEndResponse(0, 0x05, dev, 0x24, 0x00); return -1; }
+ sectors = (obj.floppy.size >> 9) - 1;
+ break;
+ case 0xB0: // DEV_CDDVD
+ if ((obj.cdrom == null) || (obj.cdrom.size == 0)) { obj.SendCommandEndResponse(0, 0x05, dev, 0x24, 0x00); return -1; }
+ sectors = (obj.cdrom.size >> 11) - 1; // Number 2048 byte blocks
+ break;
+ default:
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI Internal error 4", dev);
+ // ###END###{IDERDebug}
+ return -1;
+ }
+
+ obj.SendDataToHost(dev, true, IntToStr(8) + String.fromCharCode(0x00, 0x00, 0x0b, 0x40, 0x02, 0x00, 0x02, 0x00), featureRegister & 1);
+ break;
+ case 0x25: // READ_CAPACITY
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI: READ_CAPACITY", dev);
+ // ###END###{IDERDebug}
+ var len = 0;
+ switch(dev)
+ {
+ case 0xA0: // DEV_FLOPPY
+ if ((obj.floppy == null) || (obj.floppy.size == 0)) { obj.SendCommandEndResponse(0, 0x02, dev, 0x3a, 0x00); return -1; }
+ if (obj.floppy != null) { len = (obj.floppy.size >> 9) - 1; }
+ // ###BEGIN###{IDERDebug}
+ debug('DEV_FLOPPY', len); // Number 512 byte blocks
+ // ###END###{IDERDebug}
+ break;
+ case 0xB0: // DEV_CDDVD
+ if ((obj.cdrom == null) || (obj.cdrom.size == 0)) { obj.SendCommandEndResponse(0, 0x02, dev, 0x3a, 0x00); return -1; }
+ if (obj.cdrom != null) { len = (obj.cdrom.size >> 11) - 1; } // Number 2048 byte blocks
+ // ###BEGIN###{IDERDebug}
+ debug('DEV_CDDVD', len);
+ // ###END###{IDERDebug}
+ break;
+ default:
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI Internal error 4", dev);
+ // ###END###{IDERDebug}
+ return -1;
+ }
+ //if (dev == 0xA0) { dev = 0x00; } else { dev = 0x10; } // Weird but seems to work.
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI: READ_CAPACITY2", dev, deviceFlags);
+ // ###END###{IDERDebug}
+ obj.SendDataToHost(deviceFlags, true, IntToStr(len) + String.fromCharCode(0, 0, ((dev == 0xB0) ? 0x08 : 0x02), 0), featureRegister & 1);
+ break;
+ case 0x28: // READ_10
+ lba = ReadInt(cdb, 2);
+ len = ReadShort(cdb, 7);
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI: READ_10", dev, lba, len);
+ // ###END###{IDERDebug}
+ sendDiskData(dev, lba, len, featureRegister);
+ break;
+ case 0x2a: // WRITE_10 (Floppy only)
+ case 0x2e: // WRITE_AND_VERIFY (Floppy only)
+ lba = ReadInt(cdb, 2);
+ len = ReadShort(cdb, 7);
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI: WRITE_10", dev, lba, len);
+ // ###END###{IDERDebug}
+ obj.SendGetDataFromHost(dev, 512 * len); // Floppy writes only, accept sectors of 512 bytes
+ break;
+ case 0x43: // READ_TOC (CD Audio only)
+ var buflen = ReadShort(cdb, 7);
+ var msf = cdb.charCodeAt(1) & 0x02;
+ var format = cdb.charCodeAt(2) & 0x07;
+ if (format == 0) { format = cdb.charCodeAt(9) >> 6; }
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI: READ_TOC, dev=" + dev + ", buflen=" + buflen + ", msf=" + msf + ", format=" + format);
+ // ###END###{IDERDebug}
+
+ switch (dev) {
+ case 0xA0: // DEV_FLOPPY
+ obj.SendCommandEndResponse(1, 0x05, dev, 0x20, 0x00); // Not implemented
+ return -1;
+ case 0xB0: // DEV_CDDVD
+ // NOP
+ break;
+ default:
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI Internal error 9", dev);
+ // ###END###{IDERDebug}
+ return -1;
+ }
+
+ if (format == 1) { obj.SendDataToHost(dev, true, String.fromCharCode(0x00, 0x0a, 0x01, 0x01, 0x00, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00), featureRegister & 1); }
+ else if (format == 0) {
+ if (msf) {
+ obj.SendDataToHost(dev, true, String.fromCharCode(0x00, 0x12, 0x01, 0x01, 0x00, 0x14, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x14, 0xaa, 0x00, 0x00, 0x00, 0x34, 0x13), featureRegister & 1);
+ } else {
+ obj.SendDataToHost(dev, true, String.fromCharCode(0x00, 0x12, 0x01, 0x01, 0x00, 0x14, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00), featureRegister & 1);
+ }
+ }
+ break;
+ case 0x46: // GET_CONFIGURATION
+ var sendall = (cdb.charCodeAt(1) != 2);
+ var firstcode = ReadShort(cdb, 2);
+ var buflen = ReadShort(cdb, 7);
+
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI: GET_CONFIGURATION", dev, sendall, firstcode, buflen);
+ // ###END###{IDERDebug}
+
+ if (buflen == 0) { obj.SendDataToHost(dev, true, IntToStr(0x003c) + IntToStr(0x0008), featureRegister & 1); return -1; } // TODO: Fixed this return, it's not correct.
+
+ // Set the header
+ var r = IntToStr(0x0008);
+
+ // Add the data
+ if (firstcode == 0) { r += IDE_CD_ConfigArrayProfileList; }
+ if ((firstcode == 0x1) || (sendall && (firstcode < 0x1))) { r += IDE_CD_ConfigArrayCore; }
+ if ((firstcode == 0x2) || (sendall && (firstcode < 0x2))) { r += IDE_CD_Morphing; }
+ if ((firstcode == 0x3) || (sendall && (firstcode < 0x3))) { r += IDE_CD_ConfigArrayRemovable; }
+ if ((firstcode == 0x10) || (sendall && (firstcode < 0x10))) { r += IDE_CD_ConfigArrayRandom; }
+ if ((firstcode == 0x1E) || (sendall && (firstcode < 0x1E))) { r += IDE_CD_Read; }
+ if ((firstcode == 0x100) || (sendall && (firstcode < 0x100))) { r += IDE_CD_PowerManagement; }
+ if ((firstcode == 0x105) || (sendall && (firstcode < 0x105))) { r += IDE_CD_Timeout; }
+
+ // Set the length
+ r = IntToStr(r.length) + r;
+
+ // Cut the length to buflen if needed
+ if (r.length > buflen) { r = r.substring(0, buflen); }
+
+ obj.SendDataToHost(dev, true, r, featureRegister & 1);
+ return -1;
+ case 0x4a: // GET_EV_STATUS - GET_EVENT_STATUS_NOTIFICATION
+ //var buflen = (cdb.charCodeAt(7) << 8) + cdb.charCodeAt(8);
+ //if (buflen == 0) { obj.SendDataToHost(dev, true, IntToStr(0x003c) + IntToStr(0x0008), featureRegister & 1); return -1; } // TODO: Fixed this return, it's not correct.
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI: GET_EVENT_STATUS_NOTIFICATION", dev, cdb.charCodeAt(1), cdb.charCodeAt(4), cdb.charCodeAt(9));
+ // ###END###{IDERDebug}
+ if ((cdb.charCodeAt(1) != 0x01) && (cdb.charCodeAt(4) != 0x10)) {
+ // ###BEGIN###{IDERDebug}
+ debug('SCSI ERROR');
+ // ###END###{IDERDebug}
+ obj.SendCommandEndResponse(1, 0x05, dev, 0x26, 0x01);
+ break;
+ }
+ var present = 0x00;
+ if ((dev == 0xA0) && (obj.floppy != null)) { present = 0x02; }
+ else if ((dev == 0xB0) && (obj.cdrom != null)) { present = 0x02; }
+ obj.SendDataToHost(dev, true, String.fromCharCode(0x00, present, 0x80, 0x00), featureRegister & 1); // This is the original version, 4 bytes long
+ break;
+ case 0x4c:
+ obj.SendCommand(0x51, IntToStrX(0) + IntToStrX(0) + IntToStrX(0) + String.fromCharCode(0x87, 0x50, 0x03, 0x00, 0x00, 0x00, 0xb0, 0x51, 0x05, 0x20, 0x00), true);
+ break;
+ case 0x51: // READ_DISC_INFO
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI READ_DISC_INFO", dev);
+ // ###END###{IDERDebug}
+ obj.SendCommandEndResponse(0, 0x05, dev, 0x20, 0x00); // Correct
+ return -1;
+ case 0x55: // MODE_SELECT_10:
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI ERROR: MODE_SELECT_10", dev);
+ // ###END###{IDERDebug}
+ obj.SendCommandEndResponse(1, 0x05, dev, 0x20, 0x00);
+ return -1;
+ case 0x5a: // MODE_SENSE_10
+ // ###BEGIN###{IDERDebug}
+ debug("SCSI: MODE_SENSE_10", dev, cdb.charCodeAt(2) & 0x3f);
+ // ###END###{IDERDebug}
+ var buflen = ReadShort(cdb, 7);
+ //var pc = cdb.charCodeAt(2) & 0xc0;
+ var r = null;
+
+ if (buflen == 0) { obj.SendDataToHost(dev, true, IntToStr(0x003c) + IntToStr(0x0008), featureRegister & 1); return -1; } // TODO: Fixed this return, it's not correct.
+
+ // 1.44 mb floppy or LS120 (sectorCount == 0x3c300)
+ var sectorCount = 0;
+ if (dev == 0xA0) {
+ if (obj.floppy != null) { sectorCount = (obj.floppy.size >> 9); }
+ } else {
+ if (obj.cdrom != null) { sectorCount = (obj.cdrom.size >> 11); }
+ }
+
+ switch (cdb.charCodeAt(2) & 0x3f) {
+ case 0x01: if (dev == 0xA0) { r = (sectorCount <= 0xb40)?IDE_ModeSence_FloppyError_Recovery_Array:IDE_ModeSence_Ls120Error_Recovery_Array; } else { r = IDE_ModeSence_CDError_Recovery_Array; } break;
+ case 0x05: if (dev == 0xA0) { r = (sectorCount <= 0xb40)?IDE_ModeSence_FloppyDisk_Page_Array:IDE_ModeSence_LS120Disk_Page_Array; } break;
+ case 0x3f: if (dev == 0xA0) { r = (sectorCount <= 0xb40)?IDE_ModeSence_3F_Floppy_Array:IDE_ModeSence_3F_LS120_Array; } else { r = IDE_ModeSence_3F_CD_Array; } break;
+ case 0x1A: if (dev == 0xB0) { r = IDE_ModeSence_CD_1A_Array; } break;
+ case 0x1D: if (dev == 0xB0) { r = IDE_ModeSence_CD_1D_Array; } break;
+ case 0x2A: if (dev == 0xB0) { r = IDE_ModeSence_CD_2A_Array; } break;
+ }
+
+ if (r == null) {
+ obj.SendCommandEndResponse(0, 0x05, dev, 0x20, 0x00); // TODO: Send proper error!!!
+ } else {
+ // Set disk to read only (we don't support write).
+ //ms_data[3] = ms_data[3] | 0x80;
+ obj.SendDataToHost(dev, true, r, featureRegister & 1);
+ }
+ break;
+ default: // UNKNOWN COMMAND
+ // ###BEGIN###{IDERDebug}
+ debug("IDER: Unknown SCSI command", cdb.charCodeAt(0));
+ // ###END###{IDERDebug}
+ obj.SendCommandEndResponse(0, 0x05, dev, 0x20, 0x00);
+ return -1;
+ }
+ return 0;
+ }
+
+ function sendDiskData(dev, lba, len, featureRegister) {
+ var media = null;
+ var mediaBlocks = 0;
+ if (dev == 0xA0) { media = obj.floppy; if (obj.floppy != null) { mediaBlocks = (obj.floppy.size >> 9); } }
+ if (dev == 0xB0) { media = obj.cdrom; if (obj.cdrom != null) { mediaBlocks = (obj.cdrom.size >> 11); } }
+ if ((len < 0) || (lba + len > mediaBlocks)) { obj.SendCommandEndResponse(1, 0x05, dev, 0x21, 0x00); return 0; }
+ if (len == 0) { obj.SendCommandEndResponse(1, 0x00, dev, 0x00, 0x00); return 0; }
+ if (media != null) {
+ // Send sector stats
+ // ###BEGIN###{IDERStats}
+ if (obj.sectorStats) { obj.sectorStats(1, (dev == 0xA0) ? 0 : 1, mediaBlocks, lba, len); }
+ // ###END###{IDERStats}
+ if (dev == 0xA0) { lba <<= 9; len <<= 9; } else { lba <<= 11; len <<= 11; }
+ if (g_media !== null) {
+ // Queue read operation
+ g_readQueue.push({ media: media, dev: dev, lba: lba, len: len, fr: featureRegister });
+ } else {
+ // obj.iderinfo.readbfr // TODO: MaxRead
+ g_media = media;
+ g_dev = dev;
+ g_lba = lba;
+ g_len = len;
+ sendDiskDataEx(featureRegister);
+ }
+ }
+ }
+
+ var g_readQueue = [];
+ var g_reset = false;
+ var g_media = null;
+ var g_dev;
+ var g_lba;
+ var g_len;
+ function sendDiskDataEx(featureRegister) {
+ var len = g_len, lba = g_lba;
+ if (g_len > obj.iderinfo.readbfr) { len = obj.iderinfo.readbfr; }
+ g_len -= len;
+ g_lba += len;
+ var fr = new FileReader();
+ fr.onload = function () {
+ obj.SendDataToHost(g_dev, (g_len == 0), this.result, featureRegister & 1);
+ if ((g_len > 0) && (g_reset == false)) {
+ sendDiskDataEx(featureRegister);
+ } else {
+ g_media = null;
+ if (g_reset) { obj.SendCommand(0x47); g_readQueue = []; g_reset = false; } // Send ResetOccuredResponse
+ else if (g_readQueue.length > 0) { var op = g_readQueue.shift(); g_media = op.media; g_dev = op.dev; g_lba = op.lba; g_len = op.len; sendDiskDataEx(op.fr); } // Un-queue read operation
+ }
+ };
+ //console.log('Read from ' + lba + ' to ' + (lba + len) + ', total of ' + len);
+ fr.readAsBinaryString(g_media.slice(lba, lba + len));
+ }
+
+ return obj;
+}
diff --git a/amt-lms-0.0.1.js b/amt-lms-0.0.1.js
new file mode 100644
index 0000000..be22e97
--- /dev/null
+++ b/amt-lms-0.0.1.js
@@ -0,0 +1,104 @@
+/**
+* @description Intel AMT LMS control module - using websocket
+* @author Ylian Saint-Hilaire
+* @version v0.0.1
+*/
+
+// Construct a LMS control object
+var CreateLmsControl = function () {
+ var obj = {};
+ var socket = null;
+ obj.State = 0;
+ obj.onStateChanged = null;
+ obj.onData = null;
+
+ // Private method
+ obj.Start = function () {
+ socket = new WebSocket(window.location.protocol.replace("http", "ws") + "//" + window.location.host + "/lms.ashx");
+ socket.onopen = _OnSocketConnected;
+ socket.onmessage = _OnMessage;
+ socket.onclose = obj.Stop;
+ _StateChange(1);
+ }
+
+ function _OnSocketConnected() {
+ _StateChange(2);
+ }
+
+ // Setup the file reader
+ var fileReader = new FileReader();
+ var fileReaderInuse = false, fileReaderAcc = [];
+ if (fileReader.readAsBinaryString) {
+ // Chrome & Firefox (Draft)
+ fileReader.onload = function (e) { _OnSocketData(e.target.result); if (fileReaderAcc.length == 0) { fileReaderInuse = false; } else { fileReader.readAsBinaryString(new Blob([fileReaderAcc.shift()])); } }
+ } else if (fileReader.readAsArrayBuffer) {
+ // Chrome & Firefox (Spec)
+ fileReader.onloadend = function (e) { _OnSocketData(e.target.result); if (fileReaderAcc.length == 0) { fileReaderInuse = false; } else { fileReader.readAsArrayBuffer(fileReaderAcc.shift()); } }
+ }
+
+ function _OnMessage(e) {
+ if (typeof e.data == 'object') {
+ if (fileReaderInuse == true) { fileReaderAcc.push(e.data); return; }
+ if (fileReader.readAsBinaryString) {
+ // Chrome & Firefox (Draft)
+ fileReaderInuse = true;
+ fileReader.readAsBinaryString(new Blob([e.data]));
+ } else if (fileReader.readAsArrayBuffer) {
+ // Chrome & Firefox (Spec)
+ fileReaderInuse = true;
+ fileReader.readAsArrayBuffer(e.data);
+ } else {
+ // IE10, readAsBinaryString does not exist, use an alternative.
+ var binary = "", bytes = new Uint8Array(e.data), length = bytes.byteLength;
+ for (var i = 0; i < length; i++) { binary += String.fromCharCode(bytes[i]); }
+ _OnSocketData(binary);
+ }
+ } else {
+ _OnSocketData(e.data);
+ }
+ };
+
+ function _OnSocketData(data) {
+ if (!data) return;
+
+ if (typeof data === 'object') {
+ // This is an ArrayBuffer, convert it to a string array (used in IE)
+ var binary = "";
+ var bytes = new Uint8Array(data);
+ var length = bytes.byteLength;
+ for (var i = 0; i < length; i++) { binary += String.fromCharCode(bytes[i]); }
+ data = binary;
+ }
+ else if (typeof data !== 'string') { return; }
+
+ // Send the data up
+ if (obj.onData != null) obj.onData(obj, data);
+ }
+
+ function _Send(x) {
+ if (socket != null && socket.readyState == WebSocket.OPEN) {
+ var b = new Uint8Array(x.length);
+ for (var i = 0; i < x.length; ++i) { b[i] = x.charCodeAt(i); }
+ socket.send(b.buffer);
+ }
+ }
+
+ obj.SendCmd = function (cmdid, data) {
+ if (socket == null || obj.State != 2) return;
+ if (!data || data == null) data = "";
+ _Send(ShortToStrX(cmdid) + data);
+ }
+
+ function _StateChange(newstate) {
+ if (obj.State == newstate) return;
+ obj.State = newstate;
+ if (obj.onStateChanged != null) obj.onStateChanged(obj, obj.State);
+ }
+
+ obj.Stop = function () {
+ _StateChange(0);
+ if (socket != null) { socket.close(); socket = null; }
+ }
+
+ return obj;
+}
\ No newline at end of file
diff --git a/amt-redir-node-0.1.0.js b/amt-redir-node-0.1.0.js
new file mode 100644
index 0000000..fba1952
--- /dev/null
+++ b/amt-redir-node-0.1.0.js
@@ -0,0 +1,323 @@
+/**
+* @description Intel AMT Redirection Transport Module - using Node
+* @author Ylian Saint-Hilaire
+* @version v0.0.1f
+*/
+
+// Construct a MeshServer object
+var CreateAmtRedirect = function (module) {
+ var obj = {};
+ obj.m = module; // This is the inner module (Terminal or Desktop)
+ module.parent = obj;
+ obj.State = 0;
+ obj.net = require('net');
+ obj.tls = require('tls');
+ obj.crypto = require('crypto');
+ obj.constants = require('constants');
+ obj.socket = null;
+ obj.host = null;
+ obj.port = 0;
+ obj.user = null;
+ obj.pass = null;
+ obj.connectstate = 0;
+ obj.protocol = module.protocol; // 1 = SOL, 2 = KVM, 3 = IDER
+ obj.xtlsoptions = null;
+
+ obj.amtaccumulator = '';
+ obj.amtsequence = 1;
+ obj.amtkeepalivetimer = null;
+ obj.authuri = '/RedirectionService';
+ obj.digestRealmMatch = null;
+
+ obj.onStateChanged = null;
+
+ // Private method
+ //obj.Debug = function (msg) { console.log(msg); }
+
+ obj.Start = function (host, port, user, pass, tls, tlsFingerprint, tlsoptions) {
+ obj.host = host;
+ obj.port = port;
+ obj.user = user;
+ obj.pass = pass;
+ obj.xtls = tls;
+ obj.xtlsoptions = tlsoptions;
+ obj.xtlsFingerprint = tlsFingerprint;
+ obj.connectstate = 0;
+
+ if (obj.xtlsoptions && obj.xtlsoptions.meshServerConnect) {
+ // Use the websocket wrapper to connect to MeshServer server
+ obj.socket = CreateWebSocketWrapper(obj.xtlsoptions.host, obj.xtlsoptions.port, '/webrelay.ashx?user=' + encodeURIComponent(obj.xtlsoptions.username) + '&pass=' + encodeURIComponent(obj.xtlsoptions.password) + '&host=' + encodeURIComponent(obj.host) + '&p=2&tls=' + tlsFingerprint.xtls + '&tls1only=' + tlsFingerprint.xtlsMethod, obj.xtlsoptions.xtlsFingerprint);
+ obj.socket.setEncoding('binary');
+ obj.socket.ondata = obj.xxOnSocketData;
+ obj.socket.onclose = obj.xxOnSocketClosed;
+ obj.socket.connect(obj.xxOnSocketConnected);
+ } else if (tls == false) {
+ obj.socket = new obj.net.Socket();
+ obj.socket.setEncoding('binary');
+ obj.socket.connect(port, host, obj.xxOnSocketConnected);
+ obj.socket.on('data', obj.xxOnSocketData);
+ obj.socket.on('close', obj.xxOnSocketClosed);
+ obj.socket.on('error', obj.xxOnSocketClosed);
+ } else {
+ if (obj.xtlsoptions == null) { obj.xtlsoptions = { secureProtocol: 'TLSv1_method', ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: obj.constants.SSL_OP_NO_SSLv2 | obj.constants.SSL_OP_NO_SSLv3 | obj.constants.SSL_OP_NO_COMPRESSION | obj.constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false }; }
+ obj.socket = obj.tls.connect(port, host, obj.xtlsoptions, obj.xxOnSocketConnected);
+ obj.socket.setEncoding('binary');
+ obj.socket.on('data', obj.xxOnSocketData);
+ obj.socket.on('close', obj.xxOnSocketClosed);
+ obj.socket.on('error', obj.xxOnSocketClosed);
+ }
+ obj.xxStateChange(1);
+ }
+
+ // Get the certificate of Intel AMT
+ obj.getPeerCertificate = function () { if (obj.xtls == true) { return obj.socket.getPeerCertificate(); } return null; }
+
+ obj.xxOnSocketConnected = function () {
+ if (obj.socket == null) return;
+ if (!obj.xtlsoptions || !obj.xtlsoptions.meshServerConnect) {
+ if (obj.xtls == true) {
+ obj.xtlsCertificate = obj.socket.getPeerCertificate();
+ if ((obj.xtlsFingerprint != 0) && (obj.xtlsCertificate.fingerprint.split(':').join('').toLowerCase() != obj.xtlsFingerprint)) { obj.Stop(); return; }
+ }
+ }
+
+ if (urlvars && urlvars['redirtrace']) { console.log('REDIR-CONNECTED'); }
+ //obj.Debug("Socket Connected");
+ obj.xxStateChange(2);
+ if (obj.protocol == 1) obj.xxSend(obj.RedirectStartSol); // TODO: Put these strings in higher level module to tighten code
+ if (obj.protocol == 2) obj.xxSend(obj.RedirectStartKvm); // Don't need these is the feature if not compiled-in.
+ if (obj.protocol == 3) obj.xxSend(obj.RedirectStartIder);
+ }
+
+ obj.xxOnSocketData = function (data) {
+ if (!data || obj.connectstate == -1) return;
+ if (urlvars && urlvars['redirtrace']) { console.log('REDIR-RECV(' + data.length + '): ' + rstr2hex(data)); }
+ //obj.Debug("Recv(" + data.length + "): " + rstr2hex(data));
+ if ((obj.protocol == 2 || obj.protocol == 3) && obj.connectstate == 1) { return obj.m.ProcessData(data); } // KVM traffic, forward it directly.
+ obj.amtaccumulator += data;
+ //obj.Debug("Recv(" + obj.amtaccumulator.length + "): " + rstr2hex(obj.amtaccumulator));
+ while (obj.amtaccumulator.length >= 1) {
+ var cmdsize = 0;
+ switch (obj.amtaccumulator.charCodeAt(0)) {
+ case 0x11: // StartRedirectionSessionReply (17)
+ if (obj.amtaccumulator.length < 4) return;
+ var statuscode = obj.amtaccumulator.charCodeAt(1);
+ switch (statuscode) {
+ case 0: // STATUS_SUCCESS
+ if (obj.amtaccumulator.length < 13) return;
+ var oemlen = obj.amtaccumulator.charCodeAt(12);
+ if (obj.amtaccumulator.length < 13 + oemlen) return;
+ obj.xxSend(String.fromCharCode(0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); // Query authentication support
+ cmdsize = (13 + oemlen);
+ break;
+ default:
+ obj.Stop();
+ break;
+ }
+ break;
+ case 0x14: // AuthenticateSessionReply (20)
+ if (obj.amtaccumulator.length < 9) return;
+ var authDataLen = ReadIntX(obj.amtaccumulator, 5);
+ if (obj.amtaccumulator.length < 9 + authDataLen) return;
+ var status = obj.amtaccumulator.charCodeAt(1);
+ var authType = obj.amtaccumulator.charCodeAt(4);
+ var authData = [];
+ for (i = 0; i < authDataLen; i++) { authData.push(obj.amtaccumulator.charCodeAt(9 + i)); }
+ var authDataBuf = obj.amtaccumulator.substring(9, 9 + authDataLen);
+ cmdsize = 9 + authDataLen;
+ if (authType == 0) {
+ // ###BEGIN###{Mode-NodeWebkit}
+ if (obj.user == '*') {
+ if (authData.indexOf(2) >= 0) {
+ // Kerberos Auth
+ var ticket;
+ if (kerberos && kerberos != null) {
+ var ticketReturn = kerberos.getTicket('HTTP' + ((obj.tls == 1)?'S':'') + '/' + ((obj.pass == '') ? (obj.host + ':' + obj.port) : obj.pass));
+ if (ticketReturn.returnCode == 0 || ticketReturn.returnCode == 0x90312) {
+ ticket = ticketReturn.ticket;
+ if (process.platform.indexOf('win') >= 0) {
+ // Clear kerberos tickets on both 32 and 64bit Windows platforms
+ try { require('child_process').exec('%windir%\\system32\\klist purge', function (error, stdout, stderr) { if (error) { require('child_process').exec('%windir%\\sysnative\\klist purge', function (error, stdout, stderr) { if (error) { console.error('Unable to purge kerberos tickets'); } }); } }); } catch (e) { console.log(e); }
+ }
+ } else {
+ console.error('Unexpected Kerberos error code: ' + ticketReturn.returnCode);
+ }
+ }
+ if (ticket) {
+ obj.xxSend(String.fromCharCode(0x13, 0x00, 0x00, 0x00, 0x02) + IntToStrX(ticket.length) + ticket);
+ } else {
+ obj.Stop();
+ }
+ }
+ else obj.Stop();
+ } else {
+ // ###END###{Mode-NodeWebkit}
+ // Query
+ if (authData.indexOf(4) >= 0) {
+ // Good Digest Auth (With cnonce and all)
+ obj.xxSend(String.fromCharCode(0x13, 0x00, 0x00, 0x00, 0x04) + IntToStrX(obj.user.length + obj.authuri.length + 8) + String.fromCharCode(obj.user.length) + obj.user + String.fromCharCode(0x00, 0x00) + String.fromCharCode(obj.authuri.length) + obj.authuri + String.fromCharCode(0x00, 0x00, 0x00, 0x00));
+ }
+ else if (authData.indexOf(3) >= 0) {
+ // Bad Digest Auth (Not sure why this is supported, cnonce is not used!)
+ obj.xxSend(String.fromCharCode(0x13, 0x00, 0x00, 0x00, 0x03) + IntToStrX(obj.user.length + obj.authuri.length + 7) + String.fromCharCode(obj.user.length) + obj.user + String.fromCharCode(0x00, 0x00) + String.fromCharCode(obj.authuri.length) + obj.authuri + String.fromCharCode(0x00, 0x00, 0x00));
+ }
+ else if (authData.indexOf(1) >= 0) {
+ // Basic Auth (Probably a good idea to not support this unless this is an old version of Intel AMT)
+ obj.xxSend(String.fromCharCode(0x13, 0x00, 0x00, 0x00, 0x01) + IntToStrX(obj.user.length + obj.pass.length + 2) + String.fromCharCode(obj.user.length) + obj.user + String.fromCharCode(obj.pass.length) + obj.pass);
+ }
+ else obj.Stop();
+ // ###BEGIN###{Mode-NodeWebkit}
+ }
+ // ###END###{Mode-NodeWebkit}
+ }
+ else if ((authType == 3 || authType == 4) && status == 1) {
+ var curptr = 0;
+
+ // Realm
+ var realmlen = authDataBuf.charCodeAt(curptr);
+ var realm = authDataBuf.substring(curptr + 1, curptr + 1 + realmlen);
+ curptr += (realmlen + 1);
+
+ // Check the digest realm. If it does not match, close the connection.
+ if (obj.digestRealmMatch && (obj.digestRealmMatch != realm)) { obj.Stop(); return; }
+
+ // Nonce
+ var noncelen = authDataBuf.charCodeAt(curptr);
+ var nonce = authDataBuf.substring(curptr + 1, curptr + 1 + noncelen);
+ curptr += (noncelen + 1);
+
+ // QOP
+ var qoplen = 0;
+ var qop = null;
+ var cnonce = obj.xxRandomValueHex(32);
+ var snc = '00000002';
+ var extra = '';
+ if (authType == 4) {
+ qoplen = authDataBuf.charCodeAt(curptr);
+ qop = authDataBuf.substring(curptr + 1, curptr + 1 + qoplen);
+ curptr += (qoplen + 1);
+ extra = snc + ':' + cnonce + ':' + qop + ':';
+ }
+ var digest = hex_md5(hex_md5(obj.user + ':' + realm + ':' + obj.pass) + ':' + nonce + ':' + extra + hex_md5('POST:' + obj.authuri));
+
+ var totallen = obj.user.length + realm.length + nonce.length + obj.authuri.length + cnonce.length + snc.length + digest.length + 7;
+ if (authType == 4) totallen += (qop.length + 1);
+ var buf = String.fromCharCode(0x13, 0x00, 0x00, 0x00, authType) + IntToStrX(totallen) + String.fromCharCode(obj.user.length) + obj.user + String.fromCharCode(realm.length) + realm + String.fromCharCode(nonce.length) + nonce + String.fromCharCode(obj.authuri.length) + obj.authuri + String.fromCharCode(cnonce.length) + cnonce + String.fromCharCode(snc.length) + snc + String.fromCharCode(digest.length) + digest;
+ if (authType == 4) buf += (String.fromCharCode(qop.length) + qop);
+ obj.xxSend(buf);
+ }
+ else if (status == 0) { // Success
+ if (obj.protocol == 1) {
+ // Serial-over-LAN: Send Intel AMT serial settings...
+ var MaxTxBuffer = 10000;
+ var TxTimeout = 100;
+ var TxOverflowTimeout = 0;
+ var RxTimeout = 10000;
+ var RxFlushTimeout = 100;
+ var Heartbeat = 0;//5000;
+ obj.xxSend(String.fromCharCode(0x20, 0x00, 0x00, 0x00) + ToIntStr(obj.amtsequence++) + ToShortStr(MaxTxBuffer) + ToShortStr(TxTimeout) + ToShortStr(TxOverflowTimeout) + ToShortStr(RxTimeout) + ToShortStr(RxFlushTimeout) + ToShortStr(Heartbeat) + ToIntStr(0));
+ }
+ if (obj.protocol == 2) {
+ // Remote Desktop: Send traffic directly...
+ obj.xxSend(String.fromCharCode(0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
+ }
+ // ###BEGIN###{IDER}
+ if (obj.protocol == 3) {
+ // Remote IDER: Send traffic directly...
+ obj.connectstate = 1;
+ obj.xxStateChange(3);
+ }
+ // ###END###{IDER}
+ } else obj.Stop();
+ break;
+ case 0x21: // Response to settings (33)
+ if (obj.amtaccumulator.length < 23) break;
+ cmdsize = 23;
+ obj.xxSend(String.fromCharCode(0x27, 0x00, 0x00, 0x00) + ToIntStr(obj.amtsequence++) + String.fromCharCode(0x00, 0x00, 0x1B, 0x00, 0x00, 0x00));
+ if (obj.protocol == 1) { obj.amtkeepalivetimer = setInterval(obj.xxSendAmtKeepAlive, 2000); }
+ obj.connectstate = 1;
+ obj.xxStateChange(3);
+ break;
+ case 0x29: // Serial Settings (41)
+ if (obj.amtaccumulator.length < 10) break;
+ cmdsize = 10;
+ break;
+ case 0x2A: // Incoming display data (42)
+ if (obj.amtaccumulator.length < 10) break;
+ var cs = (10 + ((obj.amtaccumulator.charCodeAt(9) & 0xFF) << 8) + (obj.amtaccumulator.charCodeAt(8) & 0xFF));
+ if (obj.amtaccumulator.length < cs) break;
+ obj.m.ProcessData(obj.amtaccumulator.substring(10, cs));
+ cmdsize = cs;
+ break;
+ case 0x2B: // Keep alive message (43)
+ if (obj.amtaccumulator.length < 8) break;
+ cmdsize = 8;
+ break;
+ case 0x41:
+ if (obj.amtaccumulator.length < 8) break;
+ obj.connectstate = 1;
+ obj.m.Start();
+ // KVM traffic, forward rest of accumulator directly.
+ if (obj.amtaccumulator.length > 8) { obj.m.ProcessData(obj.amtaccumulator.substring(8)); }
+ cmdsize = obj.amtaccumulator.length;
+ break;
+ default:
+ console.log("Unknown Intel AMT command: " + obj.amtaccumulator.charCodeAt(0) + " acclen=" + obj.amtaccumulator.length);
+ obj.Stop();
+ return;
+ }
+ if (cmdsize == 0) return;
+ obj.amtaccumulator = obj.amtaccumulator.substring(cmdsize);
+ }
+ }
+
+ obj.xxSend = function (x) {
+ if (urlvars && urlvars['redirtrace']) { console.log('REDIR-SEND(' + x.length + '): ' + rstr2hex(x)); }
+ //obj.Debug("Send(" + x.length + "): " + rstr2hex(x));
+ obj.socket.write(new Buffer(x, 'binary'));
+ }
+
+ obj.Send = function (x) {
+ if (obj.socket == null || obj.connectstate != 1) return;
+ if (obj.protocol == 1) { obj.xxSend(String.fromCharCode(0x28, 0x00, 0x00, 0x00) + ToIntStr(obj.amtsequence++) + ToShortStr(x.length) + x); } else { obj.xxSend(x); }
+ }
+
+ obj.xxSendAmtKeepAlive = function () {
+ if (obj.socket == null) return;
+ obj.xxSend(String.fromCharCode(0x2B, 0x00, 0x00, 0x00) + ToIntStr(obj.amtsequence++));
+ }
+
+ obj.xxRandomValueHex = function(len) { return obj.crypto.randomBytes(Math.ceil(len / 2)).toString('hex').slice(0, len); }
+
+ obj.xxOnSocketClosed = function () {
+ if (urlvars && urlvars['redirtrace']) { console.log('REDIR-CLOSED'); }
+ //obj.Debug("Socket Closed");
+ obj.Stop();
+ }
+
+ obj.xxStateChange = function(newstate) {
+ if (obj.State == newstate) return;
+ obj.State = newstate;
+ obj.m.xxStateChange(obj.State);
+ if (obj.onStateChanged != null) obj.onStateChanged(obj, obj.State);
+ }
+
+ obj.Stop = function () {
+ if (urlvars && urlvars['redirtrace']) { console.log('REDIR-CLOSED'); }
+ //obj.Debug("Socket Stopped");
+ obj.xxStateChange(0);
+ obj.connectstate = -1;
+ obj.amtaccumulator = '';
+ if (obj.socket != null) { obj.socket.destroy(); obj.socket = null; }
+ if (obj.amtkeepalivetimer != null) { clearInterval(obj.amtkeepalivetimer); obj.amtkeepalivetimer = null; }
+ }
+
+ obj.RedirectStartSol = String.fromCharCode(0x10, 0x00, 0x00, 0x00, 0x53, 0x4F, 0x4C, 0x20);
+ obj.RedirectStartKvm = String.fromCharCode(0x10, 0x01, 0x00, 0x00, 0x4b, 0x56, 0x4d, 0x52);
+ obj.RedirectStartIder = String.fromCharCode(0x10, 0x00, 0x00, 0x00, 0x49, 0x44, 0x45, 0x52);
+
+ return obj;
+}
+
+function ToIntStr(v) { return String.fromCharCode((v & 0xFF), ((v >> 8) & 0xFF), ((v >> 16) & 0xFF), ((v >> 24) & 0xFF)); }
+function ToShortStr(v) { return String.fromCharCode((v & 0xFF), ((v >> 8) & 0xFF)); }
diff --git a/amt-redir-ws-0.1.0.js b/amt-redir-ws-0.1.0.js
new file mode 100644
index 0000000..9d13596
--- /dev/null
+++ b/amt-redir-ws-0.1.0.js
@@ -0,0 +1,335 @@
+/**
+* @description Intel AMT Redirection Transport Module - using websocket relay
+* @author Ylian Saint-Hilaire
+* @version v0.0.1f
+*/
+
+// Construct a MeshServer object
+var CreateAmtRedirect = function (module) {
+ var obj = {};
+ obj.m = module; // This is the inner module (Terminal or Desktop)
+ module.parent = obj;
+ obj.State = 0;
+ obj.socket = null;
+ // ###BEGIN###{!Mode-Firmware}
+ obj.host = null;
+ obj.port = 0;
+ obj.user = null;
+ obj.pass = null;
+ obj.authuri = '/RedirectionService';
+ obj.tlsv1only = 0;
+ // ###END###{!Mode-Firmware}
+ obj.connectstate = 0;
+ obj.protocol = module.protocol; // 1 = SOL, 2 = KVM, 3 = IDER
+
+ obj.amtaccumulator = '';
+ obj.amtsequence = 1;
+ obj.amtkeepalivetimer = null;
+ obj.digestRealmMatch = null;
+
+ obj.onStateChanged = null;
+
+ // Private method
+ //obj.Debug = function (msg) { console.log(msg); }
+
+ // ###BEGIN###{!Mode-Firmware}
+ obj.Start = function (host, port, user, pass, tls) {
+ obj.host = host;
+ obj.port = port;
+ obj.user = user;
+ obj.pass = pass;
+ obj.connectstate = 0;
+ obj.socket = new WebSocket(window.location.protocol.replace('http', 'ws') + '//' + window.location.host + window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) + '/webrelay.ashx?p=2&host=' + host + '&port=' + port + '&tls=' + tls + ((user == '*') ? '&serverauth=1' : '') + ((typeof pass === 'undefined') ? ('&serverauth=1&user=' + user) : '') + '&tls1only=' + obj.tlsv1only); // The "p=2" indicates to the relay that this is a REDIRECTION session
+ obj.socket.onopen = obj.xxOnSocketConnected;
+ obj.socket.onmessage = obj.xxOnMessage;
+ obj.socket.onclose = obj.xxOnSocketClosed;
+ obj.xxStateChange(1);
+ }
+ // ###END###{!Mode-Firmware}
+
+ // ###BEGIN###{Mode-Firmware}
+ obj.Start = function () {
+ obj.connectstate = 0;
+ obj.socket = new WebSocket(window.location.protocol.replace('http', 'ws') + '//' + window.location.host + '/ws-redirection');
+ obj.socket.onopen = obj.xxOnSocketConnected;
+ obj.socket.onmessage = obj.xxOnMessage;
+ obj.socket.onclose = obj.xxOnSocketClosed;
+ obj.xxStateChange(1);
+ }
+ // ###END###{Mode-Firmware}
+
+ obj.xxOnSocketConnected = function() {
+ if (urlvars && urlvars['redirtrace']) console.log('REDIR-CONNECT');
+ obj.xxStateChange(2);
+ if (obj.protocol == 1) obj.xxSend(obj.RedirectStartSol); // TODO: Put these strings in higher level module to tighten code
+ if (obj.protocol == 2) obj.xxSend(obj.RedirectStartKvm); // Don't need these is the feature is not compiled-in.
+ if (obj.protocol == 3) obj.xxSend(obj.RedirectStartIder);
+ }
+
+ // Setup the file reader
+ var fileReader = new FileReader();
+ var fileReaderInuse = false, fileReaderAcc = [];
+ if (fileReader.readAsBinaryString) {
+ // Chrome & Firefox (Draft)
+ fileReader.onload = function (e) { obj.xxOnSocketData(e.target.result); if (fileReaderAcc.length == 0) { fileReaderInuse = false; } else { fileReader.readAsBinaryString(new Blob([fileReaderAcc.shift()])); } }
+ } else if (fileReader.readAsArrayBuffer) {
+ // Chrome & Firefox (Spec)
+ fileReader.onloadend = function (e) { obj.xxOnSocketData(e.target.result); if (fileReaderAcc.length == 0) { fileReaderInuse = false; } else { fileReader.readAsArrayBuffer(fileReaderAcc.shift()); } }
+ }
+
+ obj.xxOnMessage = function (e) {
+ //if (obj.debugmode == 1) { console.log('Recv', e.data); }
+ obj.inDataCount++;
+ if (typeof e.data == 'object') {
+ if (fileReaderInuse == true) { fileReaderAcc.push(e.data); return; }
+ if (fileReader.readAsBinaryString) {
+ // Chrome & Firefox (Draft)
+ fileReaderInuse = true;
+ fileReader.readAsBinaryString(new Blob([e.data]));
+ } else if (fileReader.readAsArrayBuffer) {
+ // Chrome & Firefox (Spec)
+ fileReaderInuse = true;
+ fileReader.readAsArrayBuffer(e.data);
+ } else {
+ // IE10, readAsBinaryString does not exist, use an alternative.
+ var binary = "", bytes = new Uint8Array(e.data), length = bytes.byteLength;
+ for (var i = 0; i < length; i++) { binary += String.fromCharCode(bytes[i]); }
+ obj.xxOnSocketData(binary);
+ }
+ } else {
+ // If we get a string object, it maybe the WebRTC confirm. Ignore it.
+ // obj.debug("MeshDataChannel - OnData - " + typeof e.data + " - " + e.data.length);
+ obj.xxOnSocketData(e.data);
+ }
+ };
+
+ obj.xxOnSocketData = function (data) {
+ if (!data || obj.connectstate == -1) return;
+
+ if (typeof data === 'object') {
+ // This is an ArrayBuffer, convert it to a string array (used in IE)
+ var binary = "";
+ var bytes = new Uint8Array(data);
+ var length = bytes.byteLength;
+ for (var i = 0; i < length; i++) { binary += String.fromCharCode(bytes[i]); }
+ data = binary;
+ }
+ else if (typeof data !== 'string') { return; }
+
+ if ((obj.protocol == 2 || obj.protocol == 3) && obj.connectstate == 1) { return obj.m.ProcessData(data); } // KVM traffic, forward it directly.
+ obj.amtaccumulator += data;
+ if (urlvars && urlvars['redirtrace']) console.log("REDIR-RECV(" + obj.amtaccumulator.length + "): " + rstr2hex(obj.amtaccumulator));
+ while (obj.amtaccumulator.length >= 1) {
+ var cmdsize = 0;
+ switch (obj.amtaccumulator.charCodeAt(0)) {
+ case 0x11: // StartRedirectionSessionReply (17)
+ if (obj.amtaccumulator.length < 4) return;
+ var statuscode = obj.amtaccumulator.charCodeAt(1);
+ switch (statuscode) {
+ case 0: // STATUS_SUCCESS
+ if (obj.amtaccumulator.length < 13) return;
+ var oemlen = obj.amtaccumulator.charCodeAt(12);
+ if (obj.amtaccumulator.length < 13 + oemlen) return;
+ // ###BEGIN###{!Mode-Firmware}
+ // Query for available authentication
+ obj.xxSend(String.fromCharCode(0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)); // Query authentication support
+ // ###END###{!Mode-Firmware}
+ // ###BEGIN###{Mode-Firmware}
+ // When using websocket, we are already authenticated. Send empty basic auth.
+ obj.xxSend(String.fromCharCode(0x13, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00));
+ // ###END###{Mode-Firmware}
+ cmdsize = (13 + oemlen);
+ break;
+ default:
+ obj.Stop();
+ break;
+ }
+ break;
+ case 0x14: // AuthenticateSessionReply (20)
+ if (obj.amtaccumulator.length < 9) return;
+ var authDataLen = ReadIntX(obj.amtaccumulator, 5);
+ if (obj.amtaccumulator.length < 9 + authDataLen) return;
+ var status = obj.amtaccumulator.charCodeAt(1);
+ var authType = obj.amtaccumulator.charCodeAt(4);
+ var authData = [];
+ for (i = 0; i < authDataLen; i++) { authData.push(obj.amtaccumulator.charCodeAt(9 + i)); }
+ var authDataBuf = obj.amtaccumulator.substring(9, 9 + authDataLen);
+ cmdsize = 9 + authDataLen;
+ // ###BEGIN###{!Mode-Firmware}
+ if (authType == 0) {
+ // Query
+ if (authData.indexOf(4) >= 0) {
+ // Good Digest Auth (With cnonce and all)
+ obj.xxSend(String.fromCharCode(0x13, 0x00, 0x00, 0x00, 0x04) + IntToStrX(obj.user.length + obj.authuri.length + 8) + String.fromCharCode(obj.user.length) + obj.user + String.fromCharCode(0x00, 0x00) + String.fromCharCode(obj.authuri.length) + obj.authuri + String.fromCharCode(0x00, 0x00, 0x00, 0x00));
+ }
+ else if (authData.indexOf(3) >= 0) {
+ // Bad Digest Auth (Not sure why this is supported, cnonce is not used!)
+ obj.xxSend(String.fromCharCode(0x13, 0x00, 0x00, 0x00, 0x03) + IntToStrX(obj.user.length + obj.authuri.length + 7) + String.fromCharCode(obj.user.length) + obj.user + String.fromCharCode(0x00, 0x00) + String.fromCharCode(obj.authuri.length) + obj.authuri + String.fromCharCode(0x00, 0x00, 0x00));
+ }
+ else if (authData.indexOf(1) >= 0) {
+ // Basic Auth (Probably a good idea to not support this unless this is an old version of Intel AMT)
+ obj.xxSend(String.fromCharCode(0x13, 0x00, 0x00, 0x00, 0x01) + IntToStrX(obj.user.length + obj.pass.length + 2) + String.fromCharCode(obj.user.length) + obj.user + String.fromCharCode(obj.pass.length) + obj.pass);
+ }
+ else obj.Stop();
+ }
+ else if ((authType == 3 || authType == 4) && status == 1) {
+ var curptr = 0;
+
+ // Realm
+ var realmlen = authDataBuf.charCodeAt(curptr);
+ var realm = authDataBuf.substring(curptr + 1, curptr + 1 + realmlen);
+ curptr += (realmlen + 1);
+
+ // Check the digest realm. If it does not match, close the connection.
+ if (obj.digestRealmMatch && (obj.digestRealmMatch != realm)) { obj.Stop(); return; }
+
+ // Nonce
+ var noncelen = authDataBuf.charCodeAt(curptr);
+ var nonce = authDataBuf.substring(curptr + 1, curptr + 1 + noncelen);
+ curptr += (noncelen + 1);
+
+ // QOP
+ var qoplen = 0;
+ var qop = null;
+ var cnonce = obj.xxRandomNonce(32);
+ var snc = '00000002';
+ var extra = '';
+ if (authType == 4) {
+ qoplen = authDataBuf.charCodeAt(curptr);
+ qop = authDataBuf.substring(curptr + 1, curptr + 1 + qoplen);
+ curptr += (qoplen + 1);
+ extra = snc + ':' + cnonce + ':' + qop + ':';
+ }
+
+ var digest = hex_md5(hex_md5(obj.user + ':' + realm + ':' + obj.pass) + ':' + nonce + ':' + extra + hex_md5('POST:' + obj.authuri));
+ var totallen = obj.user.length + realm.length + nonce.length + obj.authuri.length + cnonce.length + snc.length + digest.length + 7;
+ if (authType == 4) totallen += (qop.length + 1);
+ var buf = String.fromCharCode(0x13, 0x00, 0x00, 0x00, authType) + IntToStrX(totallen) + String.fromCharCode(obj.user.length) + obj.user + String.fromCharCode(realm.length) + realm + String.fromCharCode(nonce.length) + nonce + String.fromCharCode(obj.authuri.length) + obj.authuri + String.fromCharCode(cnonce.length) + cnonce + String.fromCharCode(snc.length) + snc + String.fromCharCode(digest.length) + digest;
+ if (authType == 4) buf += (String.fromCharCode(qop.length) + qop);
+ obj.xxSend(buf);
+ }
+ else
+ // ###END###{!Mode-Firmware}
+ if (status == 0) { // Success
+ if (obj.protocol == 1) {
+ // Serial-over-LAN: Send Intel AMT serial settings...
+ var MaxTxBuffer = 10000;
+ var TxTimeout = 100;
+ var TxOverflowTimeout = 0;
+ var RxTimeout = 10000;
+ var RxFlushTimeout = 100;
+ var Heartbeat = 0;//5000;
+ obj.xxSend(String.fromCharCode(0x20, 0x00, 0x00, 0x00) + IntToStrX(obj.amtsequence++) + ShortToStrX(MaxTxBuffer) + ShortToStrX(TxTimeout) + ShortToStrX(TxOverflowTimeout) + ShortToStrX(RxTimeout) + ShortToStrX(RxFlushTimeout) + ShortToStrX(Heartbeat) + IntToStrX(0));
+ }
+ if (obj.protocol == 2) {
+ // Remote Desktop: Send traffic directly...
+ obj.xxSend(String.fromCharCode(0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
+ }
+ if (obj.protocol == 3) {
+ // Remote IDER: Send traffic directly...
+ obj.connectstate = 1;
+ obj.xxStateChange(3);
+ }
+ } else obj.Stop();
+ break;
+ case 0x21: // Response to settings (33)
+ if (obj.amtaccumulator.length < 23) break;
+ cmdsize = 23;
+ obj.xxSend(String.fromCharCode(0x27, 0x00, 0x00, 0x00) + IntToStrX(obj.amtsequence++) + String.fromCharCode(0x00, 0x00, 0x1B, 0x00, 0x00, 0x00));
+ if (obj.protocol == 1) { obj.amtkeepalivetimer = setInterval(obj.xxSendAmtKeepAlive, 2000); }
+ obj.connectstate = 1;
+ obj.xxStateChange(3);
+ break;
+ case 0x29: // Serial Settings (41)
+ if (obj.amtaccumulator.length < 10) break;
+ cmdsize = 10;
+ break;
+ case 0x2A: // Incoming display data (42)
+ if (obj.amtaccumulator.length < 10) break;
+ var cs = (10 + ((obj.amtaccumulator.charCodeAt(9) & 0xFF) << 8) + (obj.amtaccumulator.charCodeAt(8) & 0xFF));
+ if (obj.amtaccumulator.length < cs) break;
+ obj.m.ProcessData(obj.amtaccumulator.substring(10, cs));
+ cmdsize = cs;
+ break;
+ case 0x2B: // Keep alive message (43)
+ if (obj.amtaccumulator.length < 8) break;
+ cmdsize = 8;
+ break;
+ case 0x41:
+ if (obj.amtaccumulator.length < 8) break;
+ obj.connectstate = 1;
+ obj.m.Start();
+ // KVM traffic, forward rest of accumulator directly.
+ if (obj.amtaccumulator.length > 8) { obj.m.ProcessData(obj.amtaccumulator.substring(8)); }
+ cmdsize = obj.amtaccumulator.length;
+ break;
+ case 0xF0:
+ // console.log('Session is being recorded');
+ obj.serverIsRecording = true;
+ cmdsize = 1;
+ break;
+ default:
+ console.log("Unknown Intel AMT command: " + obj.amtaccumulator.charCodeAt(0) + " acclen=" + obj.amtaccumulator.length);
+ obj.Stop();
+ return;
+ }
+ if (cmdsize == 0) return;
+ obj.amtaccumulator = obj.amtaccumulator.substring(cmdsize);
+ }
+ }
+
+ obj.xxSend = function (x) {
+ if (urlvars && urlvars['redirtrace']) { console.log('REDIR-SEND(' + x.length + '): ' + rstr2hex(x)); }
+ //obj.Debug("Redir Send(" + x.length + "): " + rstr2hex(x));
+ if (obj.socket != null && obj.socket.readyState == WebSocket.OPEN) {
+ var b = new Uint8Array(x.length);
+ for (var i = 0; i < x.length; ++i) { b[i] = x.charCodeAt(i); }
+ obj.socket.send(b.buffer);
+ }
+ }
+
+ obj.Send = function (x) {
+ if (obj.socket == null || obj.connectstate != 1) return;
+ if (obj.protocol == 1) { obj.xxSend(String.fromCharCode(0x28, 0x00, 0x00, 0x00) + IntToStrX(obj.amtsequence++) + ShortToStrX(x.length) + x); } else { obj.xxSend(x); }
+ }
+
+ obj.xxSendAmtKeepAlive = function () {
+ if (obj.socket == null) return;
+ obj.xxSend(String.fromCharCode(0x2B, 0x00, 0x00, 0x00) + IntToStrX(obj.amtsequence++));
+ }
+
+ obj.xxRandomNonceX = 'abcdef0123456789';
+ obj.xxRandomNonce = function (length) {
+ var r = "";
+ for (var i = 0; i < length; i++) { r += obj.xxRandomNonceX.charAt(Math.floor(Math.random() * obj.xxRandomNonceX.length)); }
+ return r;
+ }
+
+ obj.xxOnSocketClosed = function () {
+ if (urlvars && urlvars['redirtrace']) { console.log('REDIR-CLOSED'); }
+ //obj.Debug("Redir Socket Closed");
+ obj.Stop();
+ }
+
+ obj.xxStateChange = function(newstate) {
+ if (obj.State == newstate) return;
+ obj.State = newstate;
+ obj.m.xxStateChange(obj.State);
+ if (obj.onStateChanged != null) obj.onStateChanged(obj, obj.State);
+ }
+
+ obj.Stop = function () {
+ //obj.Debug("Redir Socket Stopped");
+ obj.xxStateChange(0);
+ obj.connectstate = -1;
+ obj.amtaccumulator = "";
+ if (obj.socket != null) { obj.socket.close(); obj.socket = null; }
+ if (obj.amtkeepalivetimer != null) { clearInterval(obj.amtkeepalivetimer); obj.amtkeepalivetimer = null; }
+ }
+
+ obj.RedirectStartSol = String.fromCharCode(0x10, 0x00, 0x00, 0x00, 0x53, 0x4F, 0x4C, 0x20);
+ obj.RedirectStartKvm = String.fromCharCode(0x10, 0x01, 0x00, 0x00, 0x4b, 0x56, 0x4d, 0x52);
+ obj.RedirectStartIder = String.fromCharCode(0x10, 0x00, 0x00, 0x00, 0x49, 0x44, 0x45, 0x52);
+
+ return obj;
+}
diff --git a/amt-scanner-0.1.0.js b/amt-scanner-0.1.0.js
new file mode 100644
index 0000000..1090b73
--- /dev/null
+++ b/amt-scanner-0.1.0.js
@@ -0,0 +1,235 @@
+/**
+* @description Meshcentral Intel AMT Local Scanner
+* @author Ylian Saint-Hilaire
+* @version v0.0.1
+*/
+
+// Construct a Intel AMT Scanner object
+var CreateAmtScanner = function (func) {
+ var obj = {};
+ obj.active = false;
+ obj.dgram = require('dgram');
+ obj.servers = {};
+ obj.rserver = {};
+ obj.rpacket = null;
+ obj.tagToId = {}; // Tag --> { lastpong: time, id: NodeId }
+ obj.scanTable = {}; // Handle --> ScanInfo : { lastping: time, lastpong: time, nodeinfo:{node} }
+ obj.scanTableTags = {}; // Tag --> ScanInfo
+ obj.pendingSends = []; // We was to stagger the sends using a 10ms timer
+ obj.pendingSendTimer = null;
+ obj.mainTimer = null;
+ obj.nextTag = 0;
+ obj.computerPresenceFunc = func;
+ var PeriodicScanTime = 30000; // Interval between scan sweeps
+ var PeriodicScanTimeout = 65000; // After this time, timeout the device.
+
+ // Build a RMCP packet with a given tag field
+ obj.buildRmcpPing = function (tag) {
+ var packet = new Buffer(hex2rstr('06000006000011BE80000000'), 'ascii');
+ packet[9] = tag;
+ return packet;
+ }
+
+ // Start scanning for local network Intel AMT computers
+ obj.start = function () {
+ if (obj.active == false) {
+ obj.active = true;
+ obj.performScan();
+ obj.mainTimer = setInterval(obj.performScan, PeriodicScanTime);
+ }
+ }
+
+ // Stop scanning for local network Intel AMT computers
+ obj.stop = function () {
+ obj.active = false;
+ for (var i in obj.servers) { obj.servers[i].close(); } // Stop all servers
+ obj.servers = {};
+ if (obj.mainTimer != null) { clearInterval(obj.mainTimer); obj.mainTimer = null; }
+ }
+
+ // Scan for Intel AMT computers using network multicast
+ obj.performRangeScan = function (id, rangestr, func) {
+ if (obj.rpacket == null) { obj.rpacket = obj.buildRmcpPing(0); }
+ var range = obj.parseIpv4Range(rangestr);
+ //console.log(obj.IPv4NumToStr(range.min), obj.IPv4NumToStr(range.max));
+ if (range == null || (range.min > range.max)) return false;
+ var rangeinfo = { id: id, range: rangestr, min: range.min, max: range.max, results: {}, resultCount: 0 };
+ obj.rserver[id] = rangeinfo;
+ rangeinfo.server = obj.dgram.createSocket("udp4");
+ rangeinfo.server.bind(0);
+ rangeinfo.server.on('error', function(err) { console.log(err); });
+ rangeinfo.server.on('message', function(data, rinfo) { obj.parseRmcpPacket(data, rinfo, 0, func, rangeinfo); });
+ rangeinfo.server.on('listening', function () {
+ for (var i = rangeinfo.min; i <= rangeinfo.max; i++) {
+ rangeinfo.server.send(obj.rpacket, 0, obj.rpacket.length, 623, obj.IPv4NumToStr(i));
+ rangeinfo.server.send(obj.rpacket, 0, obj.rpacket.length, 623, obj.IPv4NumToStr(i));
+ }
+ });
+ rangeinfo.timer = setTimeout(function () {
+ if (rangeinfo.resultCount == 0) { func(obj, null); }
+ rangeinfo.server.close();
+ delete rangeinfo.server;
+ delete rangeinfo;
+ }, 5000);
+ return true;
+ }
+
+ // Parse range, used to parse "ip", "ip/mask" or "ip-ip" notation.
+ // Return the start and end value of the scan
+ obj.parseIpv4Range = function (range) {
+ if (range == undefined || range == null) return null;
+ var x = range.split('-');
+ if (x.length == 2) { return { min: obj.parseIpv4Addr(x[0]), max: obj.parseIpv4Addr(x[1]) }; }
+ x = range.split('/');
+ if (x.length == 2) {
+ var ip = obj.parseIpv4Addr(x[0]), masknum = parseInt(x[1]), mask = 0;
+ if (masknum < 16) return null;
+ for (var i = 0; i < (32 - masknum) ; i++) { mask = (mask << 1); mask++; }
+ return { min: ip & (0xFFFFFFFF - mask), max: (ip & (0xFFFFFFFF - mask)) + mask };
+ }
+ x = obj.parseIpv4Addr(range);
+ if (x == null) return null;
+ return { min: x, max: x };
+ }
+
+ // Parse IP address. Takes a
+ obj.parseIpv4Addr = function (addr) {
+ var x = addr.split('.');
+ if (x.length == 4) { return (parseInt(x[0]) << 24) + (parseInt(x[1]) << 16) + (parseInt(x[2]) << 8) + (parseInt(x[3]) << 0); }
+ return null;
+ }
+
+ // IP address number to string
+ obj.IPv4NumToStr = function (num) {
+ return ((num >> 24) & 0xFF) + '.' + ((num >> 16) & 0xFF) + '.' + ((num >> 8) & 0xFF) + '.' + (num & 0xFF);
+ }
+
+ // Scan the list of all computers
+ obj.performScan = function () {
+ if (obj.active == false || computerlist == undefined) return;
+ for (var i in obj.scanTable) { obj.scanTable[i].present = false; }
+ if (computerlist.length > 0) {
+ for (var i in computerlist) {
+ var computer = computerlist[i];
+ var host = computer.host.toLowerCase();
+ if ((host != '127.0.0.1') && (host != '::1') && (host != 'localhost') && (host.split(':').length == 1)) {
+ var scaninfo = obj.scanTable[computer.h];
+ if (scaninfo == undefined) {
+ var tag = obj.nextTag++;
+ obj.scanTableTags[tag] = obj.scanTable[computer.h] = scaninfo = { computer: computer, present: true, tag: tag, scanstate: -1, lastpong: Date.now() };
+ } else {
+ scaninfo.present = true;
+ var delta = Date.now() - scaninfo.lastpong;
+ if ((delta > PeriodicScanTimeout) && (scaninfo.scanstate != 0)) { // More than the timeout without a response, mark the node as unknown state
+ scaninfo.scanstate = 0;
+ if (obj.computerPresenceFunc) { obj.computerPresenceFunc(scaninfo.computer.h, false); }
+ }
+ }
+ // Start scanning this node
+ scaninfo.lastping = Date.now();
+ obj.checkAmtPresence(computer.host, scaninfo.tag);
+ }
+ }
+ }
+ for (var i in obj.scanTable) {
+ if (obj.scanTable[i].present == false) {
+ // Stop scanning this node
+ delete obj.scanTableTags[obj.scanTable[i].tag];
+ delete obj.scanTable[i];
+ }
+ }
+ }
+
+ // Check the presense of a specific Intel AMT computer
+ obj.checkAmtPresence = function (host, tag) {
+ var serverid = Math.floor(tag / 255);
+ var servertag = (tag % 255);
+ var packet = obj.buildRmcpPing(servertag);
+ var server = obj.servers[serverid];
+ if (server == undefined) {
+ // Start new server
+ server = obj.dgram.createSocket('udp4');
+ server.on('error', function(err) { });
+ server.on('message', function (data, rinfo) { obj.parseRmcpPacket(data, rinfo, serverid, obj.changeConnectState, null); });
+ server.on('listening', function() { obj.pendingSends.push([ server, packet, host ]); if (obj.pendingSendTimer == null) { obj.pendingSendTimer = setInterval(obj.sendPendingPacket, 10); } });
+ server.bind(0);
+ obj.servers[serverid] = server;
+ } else {
+ // Use existing server
+ obj.pendingSends.push([ server, packet, host ]);
+ if (obj.pendingSendTimer == null) { obj.pendingSendTimer = setInterval(obj.sendPendingPacket, 10); }
+ }
+ }
+
+ // Send a pending RMCP packet
+ obj.sendPendingPacket = function () {
+ try {
+ var p = obj.pendingSends.shift();
+ if (p != undefined) {
+ p[0].send(p[1], 0, p[1].length, 623, p[2]);
+ p[0].send(p[1], 0, p[1].length, 623, p[2]);
+ } else {
+ clearInterval(obj.pendingSendTimer);
+ obj.pendingSendTimer = null;
+ }
+ } catch (e) { }
+ }
+
+ // Parse RMCP packet
+ obj.parseRmcpPacket = function (data, rinfo, serverid, func, rangeinfo) {
+ if (data == null || data.length < 20) return;
+ if (((data[12] == 0) || (data[13] != 0) || (data[14] != 1) || (data[15] != 0x57)) && (data[21] & 32)) {
+ var result = { tag: (serverid * 255) + data[9], ver: ((data[18] >> 4) & 0x0F) + '.' + (data[18] & 0x0F), state: (data[19] & 0x03), port: ((data[16] * 256) + data[17]), dualport: (((data[19] & 0x04) != 0) ? true : false), rinfo: rinfo };
+ result.tls = (((result.openPort == 16993) || (result.dualPorts == true)) ? 1 : 0)
+ if (rangeinfo != null) {
+ if ((result.state <= 2) && (!rangeinfo.results[rinfo.address])) {
+ rangeinfo.results[rinfo.address] = result;
+ rangeinfo.resultCount++;
+ obj.reverseLookup(rinfo.address, function (err, domains) {
+ result.domains = domains;
+ func(obj, result, rangeinfo);
+ });
+ }
+ } else {
+ func(obj, result, rangeinfo);
+ }
+ }
+ }
+
+ // Use the RMCP packet to change the computer state
+ obj.changeConnectState = function (obj, result, rangeinfo) {
+ var scaninfo = obj.scanTableTags[result.tag];
+ if (scaninfo) {
+ scaninfo.lastpong = Date.now();
+ if (scaninfo.scanstate != 1) {
+ scaninfo.scanstate = 1;
+ if (obj.computerPresenceFunc) obj.computerPresenceFunc(scaninfo.computer.h, true);
+ }
+ }
+ }
+
+ // Perform DNS reverse lookup
+ obj.reverseLookup = function(ip, callback) {
+ var callbackCalled = false, timer = null;
+ var doCallback = function (err, domains) {
+ if (err) domains = [ip];
+ if (callbackCalled) return;
+ callbackCalled = true;
+ if (timer != null) {
+ // Cancelling timer to safe few seconds
+ clearTimeout(timer);
+ timer = null;
+ }
+ callback(err, domains);
+ }
+ // throw failed upon timeout
+ timer = setTimeout(function () {
+ timer = null; // Ensure timer is nullified
+ doCallback(new Error("Timeout exceeded"), null);
+ }, 3000);
+
+ require("dns").reverse(ip, doCallback);
+ }
+
+ return obj;
+}
\ No newline at end of file
diff --git a/amt-script-0.2.0.js b/amt-script-0.2.0.js
new file mode 100644
index 0000000..3ebfc70
--- /dev/null
+++ b/amt-script-0.2.0.js
@@ -0,0 +1,440 @@
+/**
+* @fileoverview Script Compiler / Decompiler / Runner
+* @author Ylian Saint-Hilaire
+* @version v0.1.0e
+*/
+
+// Core functions
+script_functionTable1 = ['nop', 'jump', 'set', 'print', 'dialog', 'getitem', 'substr', 'indexof', 'split', 'join', 'length', 'jsonparse', 'jsonstr', 'add', 'substract', 'parseint', 'wsbatchenum', 'wsput', 'wscreate', 'wsdelete', 'wsexec', 'scriptspeed', 'wssubscribe', 'wsunsubscribe', 'readchar', 'signwithdummyca'];
+
+// functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)
+script_functionTable2 = ['encodeuri', 'decodeuri', 'passwordcheck', 'atob', 'btoa', 'hex2str', 'str2hex', 'random', 'md5', 'maketoarray', 'readshort', 'readshortx', 'readint', 'readsint', 'readintx', 'shorttostr', 'shorttostrx', 'inttostr', 'inttostrx'];
+
+// functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)
+script_functionTableX2 = [encodeURI, decodeURI, passwordcheck, window.atob.bind(window), window.btoa.bind(window), hex2rstr, rstr2hex, random, rstr_md5, MakeToArray, ReadShort, ReadShortX, ReadInt, ReadSInt, ReadIntX, ShortToStr, ShortToStrX, IntToStr, IntToStrX];
+
+// Optional functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)
+script_functionTable3 = ['pullsystemstatus', 'pulleventlog', 'pullauditlog', 'pullcertificates', 'pullwatchdog', 'pullsystemdefense', 'pullhardware', 'pulluserinfo', 'pullremoteaccess', 'highlightblock', 'disconnect', 'getsidstring', 'getsidbytearray', 'pulleventsubscriptions'];
+
+// Optional functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)
+script_functionTableX3 = [
+ PullSystemStatus
+ ,
+ // ###BEGIN###{EventLog}
+ PullEventLog
+ // ###END###{EventLog}
+ ,
+ // ###BEGIN###{AuditLog}
+ PullAuditLog
+ // ###END###{AuditLog}
+ ,
+ // ###BEGIN###{Certificates}
+ PullCertificates
+ // ###END###{Certificates}
+ ,
+ // ###BEGIN###{AgentPresence}
+ PullWatchdog
+ // ###END###{AgentPresence}
+ ,
+ // ###BEGIN###{SystemDefense}
+ PullSystemDefense
+ // ###END###{SystemDefense}
+ ,
+ // ###BEGIN###{HardwareInfo}
+ PullHardware
+ // ###END###{HardwareInfo}
+ ,
+ PullUserInfo
+ ,
+ // ###BEGIN###{RemoteAccess}
+ PullRemoteAccess
+ // ###END###{RemoteAccess}
+ ,
+ // ###BEGIN###{Scripting-Editor}
+ script_HighlightBlock
+ // ###END###{Scripting-Editor}
+ ,
+ // ###BEGIN###{ComputerSelector}
+ disconnect
+ // ###END###{ComputerSelector}
+ ,
+ function (runner, x) { return GetSidString(x); }
+ ,
+ function (runner, x) { return GetSidByteArray(x); }
+ ,
+ // ###BEGIN###{EventSubscriptions}
+ PullEventSubscriptions
+ // ###END###{EventSubscriptions}
+];
+
+// Setup the script state
+function script_setup(binary, startvars) {
+ var obj = { startvars:startvars };
+ if (binary.length < 6) { console.error('Invalid script length'); return null; } // Script must have at least 6 byte header
+ if (ReadInt(binary, 0) != 0x247D2945) { console.error('Invalid binary script'); return null; } // Check the script magic header
+ if (ReadShort(binary, 4) > 1) { console.error('Unsupported script version'); return null; } // Check the script version
+ obj.script = binary.substring(6);
+ // obj.onStep;
+ // obj.onConsole;
+
+ // Reset the script to the start
+ obj.reset = function (stepspeed) {
+ obj.stop();
+ obj.ip = 0;
+ obj.variables = startvars;
+ obj.state = 1;
+ }
+
+ // Start the script
+ obj.start = function (stepspeed) {
+ obj.stop();
+ obj.stepspeed = stepspeed;
+ if (stepspeed > 0) { obj.timer = setInterval(function () { obj.step() }, stepspeed); }
+ }
+
+ // Stop the script
+ obj.stop = function () {
+ if (obj.timer != null) { clearInterval(obj.timer); }
+ obj.timer = null;
+ obj.stepspeed = 0;
+ }
+
+ // function used to load and store variable values
+ obj.getVar = function (name) { if (name == undefined) return undefined; return obj.getVarEx(name.split('.'), obj.variables); }
+ obj.getVarEx = function (name, val) { try { if (name == undefined) return undefined; if (name.length == 0) return val; return obj.getVarEx(name.slice(1), val[name[0]]); } catch (e) { return null; } }
+ obj.setVar = function (name, val) { obj.setVarEx(name.split('.'), obj.variables, val); }
+ obj.setVarEx = function (name, vars, val) { if (name.length == 1) { vars[name[0]] = val; } else { obj.setVarEx(name.slice(1), vars[name[0]], val); } }
+
+ // Run the script one step forward
+ obj.step = function () {
+ if (obj.state != 1) return;
+ if (obj.ip < obj.script.length) {
+ var cmdid = ReadShort(obj.script, obj.ip);
+ var cmdlen = ReadShort(obj.script, obj.ip + 2);
+ var argcount = ReadShort(obj.script, obj.ip + 4);
+ var argptr = obj.ip + 6;
+ var args = [];
+
+ // Clear all temp variables (This is optional)
+ for (var i in obj.variables) { if (i.startsWith('__')) { delete obj.variables[i]; } }
+
+ // Loop on each argument, moving forward by the argument length each time
+ for (var i = 0; i < argcount; i++) {
+ var arglen = ReadShort(obj.script, argptr);
+ var argval = obj.script.substring(argptr + 2, argptr + 2 + arglen);
+ var argtyp = argval.charCodeAt(0);
+ argval = argval.substring(1);
+ if (argtyp < 2) {
+ // Get the value and replace all {var} with variable values
+ while (argval.split("{").length > 1) { var t = argval.split("{").pop().split("}").shift(); argval = argval.replace('{' + t + '}', obj.getVar(t)); }
+ if (argtyp == 1) { obj.variables['__' + i] = decodeURI(argval); argval = '__' + i; } // If argtyp is 1, this is a literal. Store in temp variable.
+ args.push(argval);
+ }
+ if (argtyp == 2 || argtyp == 3) {
+ obj.variables['__' + i] = ReadSInt(argval, 0);
+ args.push('__' + i);
+ }
+ argptr += (2 + arglen);
+ }
+
+ // Move instruction pointer forward by command size
+ obj.ip += cmdlen;
+
+ // Get all variable values
+ var argsval = [];
+ for (var i = 0; i < 10; i++) { argsval.push(obj.getVar(args[i])); }
+ var storeInArg0;
+
+ try {
+ if (cmdid < 10000) {
+ // Lets run the actual command
+ switch (cmdid) {
+ case 0: // nop
+ break;
+ case 1: // jump(label) or jump(label, a, compare, b)
+ if (argsval[2]) {
+ if (
+ (argsval[2] == '<' && argsval[1] < argsval[3]) ||
+ (argsval[2] == '<=' && argsval[1] <= argsval[3]) ||
+ (argsval[2] == '!=' && argsval[1] != argsval[3]) ||
+ (argsval[2] == '=' && argsval[1] == argsval[3]) ||
+ (argsval[2] == '>=' && argsval[1] >= argsval[3]) ||
+ (argsval[2] == '>' && argsval[1] > argsval[3])
+ ) { obj.ip = argsval[0]; }
+ } else {
+ obj.ip = argsval[0]; // Set the instruction pointer to the new location in the script
+ }
+ break;
+ case 2: // set(variable, value)
+ if (args[1] == undefined) delete obj.variables[args[0]]; else obj.setVar(args[0], argsval[1]);
+ break;
+ case 3: // print(message)
+ if (obj.onConsole) { obj.onConsole(obj.toString(argsval[0]), obj); } else { console.log(obj.toString(argsval[0])); }
+ // Q(obj.consoleid).value += () + '\n'); Q(obj.console).scrollTop = Q(obj.console).scrollHeight;
+ break;
+ case 4: // dialog(title, content, buttons)
+ obj.state = 2;
+ obj.dialog = true;
+ setDialogMode(11, argsval[0], argsval[2], obj.xxStepDialogOk, argsval[1], obj);
+ break;
+ case 5: // getitem(a, b, c)
+ for (var i in argsval[1]) { if (argsval[1][i][argsval[2]] == argsval[3]) { storeInArg0 = i; } };
+ break;
+ case 6: // substr(variable_dest, variable_src, index, len)
+ storeInArg0 = argsval[1].substr(argsval[2], argsval[3]);
+ break;
+ case 7: // indexOf(variable_dest, variable_src, index, len)
+ storeInArg0 = argsval[1].indexOf(argsval[2]);
+ break;
+ case 8: // split(variable_dest, variable_src, separator)
+ storeInArg0 = argsval[1].split(argsval[2]);
+ break;
+ case 9: // join(variable_dest, variable_src, separator)
+ storeInArg0 = argsval[1].join(argsval[2]);
+ break;
+ case 10: // length(variable_dest, variable_src)
+ storeInArg0 = argsval[1].length;
+ break;
+ case 11: // jsonparse(variable_dest, json)
+ storeInArg0 = JSON.parse(argsval[1]);
+ break;
+ case 12: // jsonstr(variable_dest, variable_src)
+ storeInArg0 = JSON.stringify(argsval[1]);
+ break;
+ case 13: // add(variable_dest, variable_src, value)
+ storeInArg0 = (argsval[1] + argsval[2]);
+ break;
+ case 14: // substract(variable_dest, variable_src, value)
+ storeInArg0 = (argsval[1] - argsval[2]);
+ break;
+ case 15: // parseInt(variable_dest, variable_src)
+ storeInArg0 = parseInt(argsval[1]);
+ break;
+ case 16: // wsbatchenum(name, objectList)
+ obj.state = 2;
+ obj.amtstack.BatchEnum(argsval[0], argsval[1], obj.xxWsmanReturn, obj);
+ break;
+ case 17: // wsput(name, args)
+ obj.state = 2;
+ obj.amtstack.Put(argsval[0], argsval[1], obj.xxWsmanReturn, obj);
+ break;
+ case 18: // wscreate(name, args)
+ obj.state = 2;
+ obj.amtstack.Create(argsval[0], argsval[1], obj.xxWsmanReturn, obj);
+ break;
+ case 19: // wsdelete(name, args)
+ obj.state = 2;
+ obj.amtstack.Delete(argsval[0], argsval[1], obj.xxWsmanReturn, obj);
+ break;
+ case 20: // wsexec(name, method, args, selectors)
+ obj.state = 2;
+ obj.amtstack.Exec(argsval[0], argsval[1], argsval[2], obj.xxWsmanReturn, obj, 0, argsval[3]);
+ break;
+ case 21: // Script Speed
+ obj.stepspeed = argsval[0];
+ if (obj.timer != null) { clearInterval(obj.timer); obj.timer = setInterval(function () { obj.step() }, obj.stepspeed); }
+ break;
+ case 22: // wssubscribe(name, delivery, url, selectors, opaque, user, pass)
+ obj.state = 2;
+ obj.amtstack.Subscribe(argsval[0], argsval[1], argsval[2], obj.xxWsmanReturn, obj, 0, argsval[3], argsval[4], argsval[5], argsval[6]);
+ break;
+ case 23: // wsunsubscribe(name, selectors)
+ obj.state = 2;
+ obj.amtstack.UnSubscribe(argsval[0], obj.xxWsmanReturn, obj, 0, argsval[1]);
+ break;
+ case 24: // readchar(str, pos)
+ console.log(argsval[1], argsval[2], argsval[1].charCodeAt(argsval[2]));
+ storeInArg0 = argsval[1].charCodeAt(argsval[2]);
+ break;
+ case 25: // signWithDummyCa
+ // ###BEGIN###{Certificates}
+ obj.state = 2;
+ // DERKey, xxCaPrivateKey, certattributes, issuerattributes
+ amtcert_signWithCaKey(argsval[0], null, argsval[1], { 'CN': 'Untrusted Root Certificate' }, obj.xxSignWithDummyCaReturn);
+ // ###END###{Certificates}
+ break;
+ default: {
+ obj.state = 9;
+ console.error("Script Error, unknown command: " + cmdid);
+ }
+ }
+ } else {
+ if (cmdid < 20000) {
+ // functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)
+ storeInArg0 = script_functionTableX2[cmdid - 10000](argsval[1], argsval[2], argsval[3], argsval[4], argsval[5], argsval[6]);
+ } else {
+ // Optional functions of type ARG1 = func(ARG2, ARG3, ARG4, ARG5, ARG6)
+ if (script_functionTableX3 && script_functionTableX3[cmdid - 20000]) {
+ storeInArg0 = script_functionTableX3[cmdid - 20000](obj, argsval[1], argsval[2], argsval[3], argsval[4], argsval[5], argsval[6]); // Note that optional calls start with "obj" as first argument.
+ }
+ }
+ }
+
+ if (storeInArg0 != undefined) obj.setVar(args[0], storeInArg0);
+ } catch (e) {
+ if (typeof e == 'object') { e = e.message; }
+ obj.setVar('_exception', e);
+ }
+ }
+
+ if (obj.state == 1 && obj.ip >= obj.script.length) { obj.state = 0; obj.stop(); }
+ if (obj.onStep) obj.onStep(obj);
+ return obj;
+ }
+
+ obj.xxStepDialogOk = function (button) {
+ obj.variables['DialogSelect'] = button;
+ obj.state = 1;
+ obj.dialog = false;
+ if (obj.onStep) obj.onStep(obj);
+ }
+
+ // ###BEGIN###{**ClosureAdvancedMode}
+ obj.xxWsmanReturnFix = function (x) {
+ if (!x || x == null) return;
+ if (x.Header) { x['Header'] = x.Header; delete x.Header; }
+ if (x.Body) { x['Body'] = x.Body; delete x.Body; }
+ if (x.Responses) { x['Responses'] = x.Responses; delete x.Responses; }
+ if (x.Response) { x['Response'] = x.Response; delete x.Response; }
+ if (x.ReturnValueStr) { x['ReturnValueStr'] = x.ReturnValueStr; delete x.ReturnValueStr; }
+ }
+ // ###END###{**ClosureAdvancedMode}
+
+ obj.xxWsmanReturn = function (stack, name, responses, status) {
+ // ###BEGIN###{**ClosureAdvancedMode}
+ // This is required when Google Closure is used
+ if (responses) {
+ obj.xxWsmanReturnFix(responses);
+ for (var i in responses) {
+ obj.xxWsmanReturnFix(responses[i]);
+ for (var j in responses[i]) { obj.xxWsmanReturnFix(responses[i][j]); }
+ }
+ }
+ // ###END###{**ClosureAdvancedMode}
+ obj.setVar(name, responses);
+ obj.setVar('wsman_result', status);
+ obj.setVar('wsman_result_str', ((httpErrorTable[status]) ? (httpErrorTable[status]) : ('Error #' + status)));
+ obj.state = 1;
+ if (obj.onStep) obj.onStep(obj);
+ }
+
+ // ###BEGIN###{Certificates}
+ obj.xxSignWithDummyCaReturn = function (cert) {
+ obj.setVar('signed_cert', btoa(_arrayBufferToString(cert)));
+ obj.state = 1;
+ if (obj.onStep) obj.onStep(obj);
+ }
+ // ###END###{Certificates}
+
+ obj.toString = function (x) { if (typeof x == 'object') return JSON.stringify(x); return x; }
+
+ obj.reset();
+ return obj;
+}
+
+// Argument types: 0 = Variable, 1 = String, 2 = Integer, 3 = Label
+function script_compile(script, onmsg) {
+ var r = '', scriptlines = script.split('\n'), labels = {}, labelswap = [], swaps = [];
+ // Go thru each script line and encode it
+ for (var i in scriptlines) {
+ var scriptline = scriptlines[i];
+ if (scriptline.startsWith('##SWAP ')) { var x = scriptline.split(' '); if (x.length == 3) { swaps[x[1]] = x[2]; } } // Add a swap instance
+ if (scriptline[0] == '#' || scriptline.length == 0) continue; // Skip comments & blank lines
+ for (var x in swaps) { scriptline = scriptline.split(x).join(swaps[x]); } // Apply all swaps
+ var keywords = scriptline.match(/"[^"]*"|[^\s"]+/g);
+ if (keywords.length == 0) continue; // Skip blank lines
+ if (scriptline[0] == ':') { labels[keywords[0].toUpperCase()] = r.length; continue; } // Mark a label position
+ var funcIndex = script_functionTable1.indexOf(keywords[0].toLowerCase());
+ if (funcIndex == -1) { funcIndex = script_functionTable2.indexOf(keywords[0].toLowerCase()); if (funcIndex >= 0) funcIndex += 10000; }
+ if (funcIndex == -1) { funcIndex = script_functionTable3.indexOf(keywords[0].toLowerCase()); if (funcIndex >= 0) funcIndex += 20000; } // Optional methods
+ if (funcIndex == -1) { if (onmsg) { onmsg("Unabled to compile, unknown command: " + keywords[0]); } return ''; }
+ // Encode CommandId, CmdSize, ArgCount, Arg1Len, Arg1, Arg2Len, Arg2...
+ var cmd = ShortToStr(keywords.length - 1);
+ for (var j in keywords) {
+ if (j == 0) continue;
+ if (keywords[j][0] == ':') {
+ labelswap.push([keywords[j], r.length + cmd.length + 7]); // Add a label swap
+ cmd += ShortToStr(5) + String.fromCharCode(3) + IntToStr(0xFFFFFFFF); // Put an empty label
+ } else {
+ var argint = parseInt(keywords[j]);
+ if (argint == keywords[j]) {
+ cmd += ShortToStr(5) + String.fromCharCode(2) + IntToStr(argint);
+ } else {
+ if (keywords[j][0] == '"' && keywords[j][keywords[j].length - 1] == '"') {
+ cmd += ShortToStr(keywords[j].length - 1) + String.fromCharCode(1) + keywords[j].substring(1, keywords[j].length - 1);
+ } else {
+ cmd += ShortToStr(keywords[j].length + 1) + String.fromCharCode(0) + keywords[j];
+ }
+ }
+ }
+ }
+ cmd = ShortToStr(funcIndex) + ShortToStr(cmd.length + 4) + cmd;
+ r += cmd;
+ }
+ // Perform all the needed label swaps
+ for (i in labelswap) {
+ var label = labelswap[i][0].toUpperCase(), position = labelswap[i][1], target = labels[label];
+ if (target == undefined) { if (onmsg) { onmsg("Unabled to compile, unknown label: " + label); } return ''; }
+ r = r.substr(0, position) + IntToStr(target) + r.substr(position + 4);
+ }
+ return IntToStr(0x247D2945) + ShortToStr(1) + r;
+}
+
+// Decompile the script, intended for debugging only
+function script_decompile(binary, onecmd) {
+ var r = '', ptr = 6, labelcount = 0, labels = {};
+ if (onecmd >= 0) {
+ ptr = onecmd; // If we are decompiling just one command, set the ptr to that command.
+ } else {
+ if (binary.length < 6) { return '# Invalid script length'; }
+ var magic = ReadInt(binary, 0);
+ var version = ReadShort(binary, 4);
+ if (magic != 0x247D2945) { return '# Invalid binary script: ' + magic; }
+ if (version != 1) { return '# Invalid script version'; }
+ }
+ // Loop on each command, moving forward by the command length each time.
+ while (ptr < binary.length) {
+ var cmdid = ReadShort(binary, ptr);
+ var cmdlen = ReadShort(binary, ptr + 2);
+ var argcount = ReadShort(binary, ptr + 4);
+ var argptr = ptr + 6;
+ var argstr = '';
+ if (!(onecmd >= 0)) r += ":label" + (ptr - 6) + "\n";
+ // Loop on each argument, moving forward by the argument length each time
+ for (var i = 0; i < argcount; i++) {
+ var arglen = ReadShort(binary, argptr);
+ var argval = binary.substring(argptr + 2, argptr + 2 + arglen);
+ var argtyp = argval.charCodeAt(0);
+ if (argtyp == 0) { argstr += ' ' + argval.substring(1); } // Variable
+ else if (argtyp == 1) { argstr += ' \"' + argval.substring(1) + '\"'; } // String
+ else if (argtyp == 2) { argstr += ' ' + ReadInt(argval, 1); } // Integer
+ else if (argtyp == 3) { // Label
+ var target = ReadInt(argval, 1);
+ var label = labels[target];
+ if (!label) { label = ":label" + target; labels[label] = target; }
+ argstr += ' ' + label;
+ }
+ argptr += (2 + arglen);
+ }
+ // Go in the script function table to decode the function
+ if (cmdid < 10000) {
+ r += script_functionTable1[cmdid] + argstr + "\n";
+ } else {
+ if (cmdid >= 20000) {
+ r += script_functionTable3[cmdid - 20000] + argstr + "\n"; // Optional methods
+ } else {
+ r += script_functionTable2[cmdid - 10000] + argstr + "\n";
+ }
+ }
+ ptr += cmdlen;
+ if (onecmd >= 0) return r; // If we are decompiling just one command, exit now
+ }
+ // Remove all unused labels
+ var scriptlines = r.split('\n');
+ r = '';
+ for (var i in scriptlines) {
+ var line = scriptlines[i];
+ if (line[0] != ':') { r += line + '\n'; } else { if (labels[line]) { r += line + '\n'; } }
+ }
+ return r;
+}
diff --git a/amt-setupbin-0.1.0.js b/amt-setupbin-0.1.0.js
new file mode 100644
index 0000000..1797bae
--- /dev/null
+++ b/amt-setupbin-0.1.0.js
@@ -0,0 +1,273 @@
+/**
+* @description Intel(R) AMT Setup.bin Parser
+* @author Ylian Saint-Hilaire
+* @version v0.1.0
+*/
+
+// Intel(R) AMT Setup.bin GUID's
+var AmtSetupBinSetupGuids = [
+ "\xb5\x16\xfb\x71\x87\xcb\xf9\x4a\xb4\x41\xca\x7b\x38\x35\x78\xf9", // Version 1
+ "\x96\xb2\x81\x58\xcf\x6b\x72\x4c\x8b\x91\xa1\x5e\x51\x2e\x99\xc4", // Version 2
+ "\xa7\xf7\xf6\xc6\x89\xc4\xf6\x47\x93\xed\xe2\xe5\x02\x0d\xa5\x1d", // Version 3
+ "\xaa\xa9\x34\x52\xe1\x29\xa9\x44\x8d\x4d\x08\x1c\x07\xb9\x63\x53" // Version 4
+];
+
+// Notes about version 2 of setup.bin:
+// - Default "admin" must be followed by a new MEBx password
+// - ME_VARIABLE_IDENTIFIER_MANAGEABILITY_FEATURE_SELECTION may not appear after any CM settings
+// - CM_VARIABLE_IDENTIFIER_USER_DEFINED_CERT_ADD must be preceded by setting CM_VARIABLE_IDENTIFIER_USER_DEFINED_CERTS_CONFIG to (TODO!)
+
+// General notes:
+// - Setup.bin should always start with "CurrentMEBx Pwd", "newMebx Pwd", "manageability selection" (if present).
+
+// Intel(R) AMT variable identifiers
+// Type: 0 = Binar Stringy, 1 = Char, 2 = Short, 3 = Int
+var AmtSetupBinVarIds =
+{
+ 1: {
+ 1: [0, "Current MEBx Password"],
+ 2: [0, "New MEBx Password"],
+ 3: [1, "Manageability Feature Selection",
+ { 0: "None", 1: "Intel AMT" }],
+ 4: [1, "Firmware Local Update", // 0 = Disabled, 1 = Enabled, 2 = Password Protected
+ { 0: "Disabled", 1: "Enabled", 2: "Password Protected" }],
+ 5: [1, "Firmware Update Qualifier", // 0 = Always, 1 = Never, 2 = Restricted
+ { 0: "Always", 1: "Never", 2: "Restricted" }],
+ 6: [4, "Power Package"] // GUID Length (16 bytes), Intel AMT version 2.1, 3 and 4
+ },
+ 2: {
+ 1: [0, "Provisioning Preshared Key ID (PID)"],
+ 2: [0, "Provisioning Preshared Key (PPS)"],
+ 3: [0, "PKI DNS Suffix"], // 255 bytes max length
+ 4: [0, "Configuration Server FQDN"], // 255 bytes max length
+ 5: [1, "Remote Configuration Enabled (RCFG)", // 0 = Off, 1 = On
+ { 0: "Off", 1: "On" }],
+ 6: [1, "Pre-Installed Certificates Enabled", // 0 = Off, 1 = On
+ { 0: "Off", 1: "On" }],
+ 7: [1, "User Defined Certificate Configuration", // 0 = Disabled, 1 = Enabled, 2 = Delete
+ { 0: "Disabled", 1: "Enabled", 2: "Delete" }],
+ 8: [0, "User Defined Certificate Addition"], // 1 byte hash algo, 20 to 48 bytes hash, 1 byte name length, up to 32 bytes friendly name, 1 = SHA1 (20 bytes), 2 = SHA256 (32 bytes), 3 = SHA384 (48 bytes). Algo 2 & 3 are for version 3 and up.
+ 10: [1, "SOL/IDER Redirection Configuration", {
+ 0: "None", 1: "SOL only - User/Pass Disabled", 2: "IDER only - User/Pass Disabled", 3: "SOL+IDER - User/Pass Disabled",
+ 4: "None - User/Pass Enabled", 5: "SOL only - User/Pass Enabled", 6: "IDER only - User/Pass Enabled", 7: "SOL+IDER - User/Pass Enabled"
+ }],
+ 11: [0, "Hostname"], // 63 bytes max length
+ 12: [0, "Domain Name"], // 255 bytes max length
+ 13: [1, "DHCP", { 1: "Disabled", 2: "Enabled" }],
+ 14: [1, "Secure Firmware Update (SFWU)", // 0 = Disabled, 1 = Enabled
+ { 0: "Disabled", 1: "Enabled" }],
+ 15: [0, "ITO"],
+ 16: [1, "Provisioning Mode (PM)", // 1 = Enterprise, 2 = Small Buisness (SMB)
+ { 0: "Enterprise", 1: "Small Buisness"}],
+ 17: [0, "Provisioning Server Address"],
+ 18: [2, "Provision Server Port Number (PSPO)"],
+ 19: [0, "Static IPv4 Parameters"],
+ 20: [0, "VLAN"],
+ 21: [0, "PASS Policy Flag"],
+ 22: [0, "IPv6"], // Length is 204 bytes old format, 84 bytes new format, Version 3+ only
+ 23: [1, "Shared/Dedicated FQDN", // 0 = Dedicated, 1 = Shared. This option is valid only if configuring the hostname as well
+ { 0: "Dedicated", 1: "Shared" }],
+ 24: [1, "Dynamic DNS Update", // 0 = Disabled, 1 = Enabled
+ { 0: "Disabled", 1: "Enabled" }],
+ 25: [1, "Remote Desktop (KVM) State", // 0 = Disabled, 1 = Enabled
+ { 0: "Disabled", 1: "Enabled" }],
+ 26: [1, "Opt-in User Consent Option", // 0 = Disabled, 1 = KVM, 0xFF = ALL
+ { 0 : "Disabled", 1 : "KVM", 255 : "All" }],
+ 27: [1, "Opt-in Remote IT Consent Policy", // 0 = Disabled, 1 = Enabled. Allows user consent to be configured remotely.
+ { 0 : "Disabled", 1 : "Enabled"} ],
+ 28: [1, "ME Provision Halt Active", // 0 = Stop, 1 = Start. The "ME provisioning Halt/Activate" command must appear in the file only after "PKIDNSSuffix", "ConfigServerFQDN" and "Provisioning Server Address"
+ { 0 : "Stop", 1 : "Start"}],
+ 29: [1, "Manual Setup and Configuration", // 0 = Automated, 1 = Manual
+ { 0 : "Automated", 1 : "Manual"}],
+ 30: [3, "Support Channel Identifier"], // 4 bytes length. Support channel identifier (valid values: 1-65535)
+ 31: [0, "Support Channel Description"], // 60 bytes max. Friendly name used to describe the party representedby the support channel identifier.
+ 32: [0, "Service Account Number"], // 32 bytes max. Unique string identifier given to the end user by the service provider.
+ 33: [0, "Enrollement Passcode"], // 32 bytes max
+ 34: [3, "Service Type"], // 4 bytes length. 1 = Reactive, 2 = Proactive, 4 = One Time Session
+ 35: [0, "Service Provider Identifier"] // GUID Length (16 bytes)
+ }
+}
+
+
+// Parse the Setup.bin file
+var AmtSetupBinCreate = function (version, flags) {
+ var obj = {};
+ obj.fileType = version;
+ obj.recordChunkCount = 0;
+ obj.recordHeaderByteCount = 0;
+ obj.recordNumber = 0;
+ obj.majorVersion = version;
+ obj.minorVersion = 0;
+ obj.flags = flags;
+ obj.dataRecordsConsumed = 0;
+ obj.dataRecordChunkCount = 0;
+ obj.records = [];
+ return obj;
+}
+
+
+// Parse the Setup.bin file
+var AmtSetupBinDecode = function (file) {
+
+ // Format of the setup file header:
+ // FileTypeUUID(16) - uniquely identifies the file type. This identifier will remain valid and constant across all versions of the file type.
+ // RecordChunkCount(2) - indicates the number of 512-byte chunks occupied by this record, including all header, body, and reserved fields.
+ // RecordHeaderBytes(2) - indicates the length of the record header in bytes.
+ // RecordNumber(4) - uniquely identifies the record among all records in the file. The field contains a non-negative ordinal value. The value of this field is always zero in the Local Provisioning File Header Record.
+ // MajorVersion(1) - identifies the major version of the file format specification. This is a positive integer that is greater than or equal to 1. The Major Version number is incremented to indicate that changes have been introduced that will cause code written against a lower Major Version number to fail.
+ // MinorVersion(1) - identifies the minor version of the file format specification. This is an integer that is greater than or equal to 0. The Minor Version number is incremented to indicate that changes have been introduced that will not cause code written against the same Major Version and a lower Minor Version number to fail. The purpose of this behavior is to allow a single local provisioning file to be used for multiple generations of Intel® AMT platform.
+ // DataRecordCount(4) - indicates the total number of data records written in the file when it was created.
+ // DataRecordsConsumed(4) - is a counter value that begins at 0 and is incremented by 1 by each platform BIOS when it consumes a data record from the file. This value is used to determine the offset of the next data record in the file.
+ // DataRecordChunkCount(2) - contains the number of 512-byte chunks in each data record. All data records are the same length.
+ // ModuleList - contains a list of module identifiers. A module’s identifier appears in the list if and only if the data records contain entries for that module. Each module identifier is two bytes in length. The list is terminated by an identifier value of 0.
+
+ var obj = {}, UUID = file.substring(0, 16);
+ obj.fileType = 0;
+ for (var i in AmtSetupBinSetupGuids) { if (UUID == AmtSetupBinSetupGuids[i]) obj.fileType = (+i + 1); }
+ if (obj.fileType == 0) return; // Bad header
+ obj.recordChunkCount = ReadShortX(file, 16);
+ obj.recordHeaderByteCount = ReadShortX(file, 18);
+ obj.recordNumber = ReadIntX(file, 20);
+ obj.majorVersion = file.charCodeAt(24);
+ obj.minorVersion = file.charCodeAt(25);
+ obj.flags = ReadShortX(file, 26); // Flags: 1 = Do not consume records
+ var dataRecordCount = ReadIntX(file, 28);
+ obj.dataRecordsConsumed = ReadIntX(file, 32);
+ obj.dataRecordChunkCount = ReadShortX(file, 36);
+ obj.records = [];
+
+ var ptr = 512;
+ while (ptr + 512 <= file.length) {
+
+ // Format of a data record header:
+ // RecordTypeIdentifier(4) - identifies the type of record (in this case a data record). Record Identifiers: Invalid - 0, Data Record - 1
+ // RecordFlags(4) - contains a set of bit flags that characterize the record.
+ // RecordChunkCount(2) - contains the number of 512-byte chunks occupied by the record including all header, body, and reserved fields.
+ // RecordHeaderByteCount(2) - indicates the length of the record header in bytes.
+ // RecordNumber(4) - uniquely identifies the record among all records in the file, including invalid as well as valid records. The identifier is a non-negative integer.
+
+ var r = {};
+ r.typeIdentifier = ReadIntX(file, ptr);
+ r.flags = ReadIntX(file, ptr + 4); // Flags: 1 = Valid, 2 = Scrambled
+ r.chunkCount = ReadShortX(file, ptr + 8);
+ r.headerByteCount = ReadShortX(file, ptr + 10);
+ r.number = ReadIntX(file, ptr + 12);
+ r.variables = [];
+
+ var ptr2 = 0, recbin = file.substring(ptr + 24, ptr + 512);
+ if ((r.flags & 2) != 0) { recbin = AmtSetupBinDescrambleRecordData(recbin); } // De-Scramble the record
+ while (1) {
+
+ // Format of a data record entry:
+ // ModuleIdentifier(2) - identifies the target ME module for the entry.
+ // VariableIdentifier(2) - an enumeration value that identifies the variable. Variable identifiers are unique to each ModuleIdentifier.
+ // VariableLength(2) - is the length of the variable value in bytes.
+ // VariableValue - is the value to be assigned to the variable.
+
+ var v = {};
+ v.moduleid = ReadShortX(recbin, ptr2);
+ v.varid = ReadShortX(recbin, ptr2 + 2);
+ if (v.moduleid == 0 || v.varid == 0) break;
+ if (AmtSetupBinVarIds[v.moduleid][v.varid]) {
+ v.length = ReadShortX(recbin, ptr2 + 4);
+ v.type = AmtSetupBinVarIds[v.moduleid][v.varid][0];
+ v.desc = AmtSetupBinVarIds[v.moduleid][v.varid][1];
+ v.value = recbin.substring(ptr2 + 8, ptr2 + 8 + v.length);
+ if (v.type == 1 && v.length == 1) v.value = v.value.charCodeAt(0); // 1 byte number
+ else if (v.type == 2 && v.length == 2) v.value = ReadShortX(v.value, 0); // 2 byte number
+ else if (v.type == 3 && v.length == 4) v.value = ReadIntX(v.value, 0); // 4 byte number
+ else if (v.type == 4) v.value = guidToStr(rstr2hex(v.value)); // GUID
+ r.variables.push(v);
+ }
+ ptr2 += (8 + (Math.floor((v.length + 3) / 4) * 4));
+ }
+
+ // Sort the variables
+ r.variables.sort(AmtSetupBinVariableCompare);
+
+ obj.records.push(r);
+ ptr += 512;
+ }
+
+ if (dataRecordCount != obj.records.length) return; // Mismatch record count
+ return obj;
+}
+
+// Construct a Setup.bin file
+var AmtSetupBinEncode = function (obj) {
+ if (obj.fileType < 1 && obj.fileType > AmtSetupBinSetupGuids.length) return null;
+ var out = [], r = AmtSetupBinSetupGuids[obj.fileType - 1], reccount = 0;
+ r += ShortToStrX(obj.recordChunkCount);
+ r += ShortToStrX(obj.recordHeaderByteCount);
+ r += IntToStrX(obj.recordNumber);
+ r += String.fromCharCode(obj.majorVersion, obj.minorVersion);
+ r += ShortToStrX(obj.flags); // Flags: 1 = Do not consume records
+ r += IntToStrX(obj.records.length);
+ r += IntToStrX(obj.dataRecordsConsumed);
+ r += ShortToStrX(obj.dataRecordChunkCount);
+ while (r.length < 512) { r += "\0"; } // Pad the header
+ out.push(r);
+
+ // Write each record
+ for (var i in obj.records) {
+ var r2 = "", rec = obj.records[i];
+ r2 += IntToStrX(rec.typeIdentifier);
+ r2 += IntToStrX(rec.flags);
+ r2 += IntToStrX(0); // Reserved
+ r2 += IntToStrX(0); // Reserved
+ r2 += ShortToStrX(1); // rec.chunkCount
+ r2 += ShortToStrX(24); // rec.headerByteCount
+ r2 += IntToStrX(++reccount);
+
+ // Sort the variables
+ rec.variables.sort(AmtSetupBinVariableCompare);
+
+ /*
+ // Change variable priority
+ AmtSetupBinMoveToTop(r.variables, 1, 3); // Manageability Feature Selection
+ AmtSetupBinMoveToTop(r.variables, 1, 2); // New MEBx password
+ AmtSetupBinMoveToTop(r.variables, 1, 1); // Current MEBx password
+ */
+
+ // Write each variable
+ for (var j in rec.variables) {
+ var r3 = "", v = rec.variables[j], data = v.value;
+ v.type = AmtSetupBinVarIds[v.moduleid][v.varid][0]; // Set the correct type if not alreay connect
+ if ((v.type > 0) && (v.type < 4)) { // If this is a numeric value, encode it correctly
+ data = parseInt(data);
+ if (v.type == 1) data = String.fromCharCode(data);
+ if (v.type == 2) data = ShortToStrX(data);
+ if (v.type == 3) data = IntToStrX(data);
+ }
+ if (v.type == 4) { data = hex2rstr(guidToStr(data.split('-').join('')).split('-').join('')); }
+ r3 += ShortToStrX(v.moduleid); // Module Identifier
+ r3 += ShortToStrX(v.varid); // Variable Identifier
+ r3 += ShortToStrX(data.length); // Variable Length
+ r3 += ShortToStrX(0); // Reserved
+ r3 += data; // Variable Data
+ while (r3.length % 4 != 0) { r3 += "\0"; } // Pad the variable
+ r2 += r3;
+ }
+
+ while (r2.length < 512) { r2 += "\0"; } // Pad the record
+ if ((rec.flags & 2) != 0) { r2 = r2.substring(0, 24) + AmtSetupBinScrambleRecordData(r2.substring(24)); } // Scramble the record starting at byte 24, after the header
+ out.push(r2);
+ }
+ return out.join('');
+}
+
+// Used to sort variables
+function AmtSetupBinVariableCompare(a, b) {
+ if (a.moduleid > b.moduleid) return 1;
+ if (a.moduleid < b.moduleid) return -1;
+ if (a.varid > b.varid) return 1;
+ if (a.varid < b.varid) return -1;
+ return 0;
+}
+
+// Scramble and un-scramble records
+function AmtSetupBinScrambleRecordData(data) { var out = ""; for (var i = 0; i < data.length; i++) { out += String.fromCharCode((data.charCodeAt(i) + 17) & 0xFF); } return out; }
+function AmtSetupBinDescrambleRecordData(data) { var out = ""; for (var i = 0; i < data.length; i++) { out += String.fromCharCode((data.charCodeAt(i) + 0xEF) & 0xFF); } return out; }
+
+// Find a moduleid/varid in the variable list, if found, move it to the top
+//function AmtSetupBinMoveToTop(variables, moduleid, varid) { var i = -1; for (var j in variables) { if ((variables[j].moduleid == moduleid) && (variables[j].varid == varid)) { i = j; } } if (i > 1) { ArrayElementMove(variables, i, 0); } }
diff --git a/amt-terminal-0.0.2.js b/amt-terminal-0.0.2.js
new file mode 100644
index 0000000..fb2ee4a
--- /dev/null
+++ b/amt-terminal-0.0.2.js
@@ -0,0 +1,813 @@
+/**
+* @description Remote Terminal
+* @author Ylian Saint-Hilaire
+* @version v0.0.2c
+*/
+
+// https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
+// https://www.x.org/docs/xterm/ctlseqs.pdf
+
+// Construct a MeshServer object
+var CreateAmtRemoteTerminal = function (divid, options) {
+ var obj = {};
+ obj.DivId = divid;
+ obj.DivElement = document.getElementById(divid);
+ obj.protocol = 1; // SOL
+ if (options && options.protocol) { obj.protocol = options.protocol; } // 1 = Normal, 6 = PowerShell
+ // ###BEGIN###{Terminal-Enumation-All}
+ obj.terminalEmulation = 1;
+ // ###END###{Terminal-Enumation-All}
+ obj.fxEmulation = 0;
+ obj.lineFeed = '\r\n';
+ obj.debugmode = 0;
+
+ obj.width = 80; // 80 or 100
+ obj.height = 25; // 25 or 30
+ obj.heightLock = 0;
+
+ var _Terminal_CellHeight = 21;
+ var _Terminal_CellWidth = 13;
+ var _TermColors = ['000000', 'BB0000', '00BB00', 'BBBB00', '0000BB', 'BB00BB', '00BBBB', 'BBBBBB', '555555', 'FF5555', '55FF55', 'FFFF55', '5555FF', 'FF55FF', '55FFFF', 'FFFFFF'];
+ var _TermCurrentReverse = 0;
+ var _TermCurrentFColor = 7;
+ var _TermCurrentBColor = 0;
+ var _TermLineWrap = true;
+ var _termx = 0;
+ var _termy = 0;
+ var _termsavex = 0;
+ var _termsavey = 0;
+ var _termstate = 0;
+ var _escNumber = [];
+ var _escNumberPtr = 0;
+ var _escNumberMode = 0;
+ var _scratt = [];
+ var _tscreen = [];
+ var _VTUNDERLINE = 1;
+ var _VTREVERSE = 2;
+ var _backSpaceErase = false;
+ var _cursorVisible = true;
+ var _scrollRegion;
+ var _altKeypadMode = false;
+ var scrollBackBuffer = [];
+ // ###BEGIN###{Terminal-Enumation-UTF8}
+ var utf8decodeBuffer = '';
+ // ###END###{Terminal-Enumation-UTF8}
+ // ###BEGIN###{Terminal-Enumation-All}
+ var utf8decodeBuffer = '';
+ // ###END###{Terminal-Enumation-All}
+ obj.title = null;
+ obj.onTitleChange = null;
+
+ obj.Start = function () { }
+
+ obj.Init = function (width, height) {
+ obj.width = width ? width : 80;
+ obj.height = height ? height : 25;
+ for (var y = 0; y < obj.height; y++) {
+ _tscreen[y] = [];
+ _scratt[y] = [];
+ for (var x = 0; x < obj.width; x++) { _tscreen[y][x] = ' '; _scratt[y][x] = (7 << 6); }
+ }
+ obj.TermInit();
+ obj.TermDraw();
+ }
+
+ obj.xxStateChange = function (newstate) {
+ if ((newstate == 3) && (options != null) && (options.xterm == true)) { obj.TermSendKeys('stty rows ' + obj.height + ' cols ' + obj.width + '\nclear\n'); }
+ }
+
+ obj.ProcessData = function (str) {
+ if (obj.debugmode == 2) { console.log("TRecv(" + str.length + "): " + rstr2hex(str)); }
+ if (obj.capture != null) obj.capture += str;
+ // ###BEGIN###{Terminal-Enumation-UTF8}
+ try { str = decode_utf8(utf8decodeBuffer + str); } catch (ex) { utf8decodeBuffer += str; return; } // If we get data in the middle of a UTF-8 code, buffer it for next time.
+ utf8decodeBuffer = '';
+ // ###END###{Terminal-Enumation-UTF8}
+ // ###BEGIN###{Terminal-Enumation-All}
+ if (obj.terminalEmulation == 0) { try { str = decode_utf8(utf8decodeBuffer + str); } catch (ex) { utf8decodeBuffer += str; return; } } // If we get data in the middle of a UTF-8 code, buffer it for next time.
+ utf8decodeBuffer = '';
+ // ###END###{Terminal-Enumation-All}
+ _ProcessVt100EscString(str); obj.TermDraw();
+ }
+
+ function _ProcessVt100EscString(str) { for (var i = 0; i < str.length; i++) _ProcessVt100EscChar(String.fromCharCode(str.charCodeAt(i)), str.charCodeAt(i)); }
+
+ function _ProcessVt100EscChar(b, c) {
+ switch (_termstate) {
+ case 0: // Normal Term State
+ switch (c) {
+ case 27: // ESC
+ _termstate = 1;
+ _escNumber = [];
+ _escNumberPtr = 0;
+ _escNumberMode = 0;
+ break;
+ default:
+ // Process a single char
+ _ProcessVt100Char(b);
+ break;
+ }
+ break;
+ case 1:
+ switch (b) {
+ case '[':
+ _termstate = 2;
+ break;
+ case '(':
+ _termstate = 4;
+ break;
+ case ')':
+ _termstate = 5;
+ break;
+ case ']':
+ _termstate = 6; // xterm strings
+ break;
+ case '=':
+ // Set alternate keypad mode
+ _altKeypadMode = true;
+ _termstate = 0;
+ break;
+ case '>':
+ // Set numeric keypad mode
+ _altKeypadMode = false;
+ _termstate = 0;
+ break;
+ case '7':
+ // Save Cursor
+ _termsavex = _termx;
+ _termsavey = _termy;
+ _termstate = 0;
+ break;
+ case '8':
+ // Restore Cursor
+ _termx = _termsavex;
+ _termy = _termsavey;
+ _termstate = 0;
+ break;
+ case 'M':
+ // Scroll down one
+ var x = 1;
+ for (var y = _scrollRegion[1]; y >= _scrollRegion[0] + x; y--) {
+ for (var z = 0; z < obj.width; z++) { _tscreen[y][z] = _tscreen[y - x][z]; _scratt[y][z] = _scratt[y - x][z]; }
+ }
+ for (var y = _scrollRegion[0] + x - 1; y > _scrollRegion[0] - 1; y--) {
+ for (var z = 0; z < obj.width; z++) { _tscreen[y][z] = ' '; _scratt[y][z] = (7 << 6); }
+ }
+ _termstate = 0;
+ break;
+ default:
+ console.log('unknown terminal short code', b);
+ _termstate = 0;
+ break;
+ }
+ break;
+ case 2:
+ if (b >= '0' && b <= '9') {
+ // This is a number
+ if (!_escNumber[_escNumberPtr]) { _escNumber[_escNumberPtr] = (b - '0'); }
+ else { _escNumber[_escNumberPtr] = ((_escNumber[_escNumberPtr] * 10) + (b - '0')); }
+ break;
+ } else if (b == ';') {
+ // New number
+ _escNumberPtr++;
+ break;
+ } else if (b == '?') {
+ _escNumberMode = 1;
+ break;
+ } else {
+ // Process Escape Sequence
+ if (!_escNumber[0]) _escNumber[0] = 0;
+ _ProcessEscapeHandler(b, _escNumber, _escNumberPtr + 1, _escNumberMode);
+ _termstate = 0;
+ }
+ break;
+ case 4: // '(' Code
+ _termstate = 0;
+ break;
+ case 5: // ')' Code
+ _termstate = 0;
+ break;
+ case 6: // ']' Code, xterm
+ var bx = b.charCodeAt(0);
+ if (b == ';') {
+ _escNumberPtr++;
+ } else if (bx == 7) {
+ _ProcessXTermHandler(_escNumber);
+ _termstate = 0;
+ } else {
+ if (!_escNumber[_escNumberPtr]) { _escNumber[_escNumberPtr] = b; }
+ else { _escNumber[_escNumberPtr] += b; }
+ }
+ break;
+ }
+ }
+
+ function _ProcessXTermHandler(_escNumber) {
+ if (_escNumber.length == 0) return;
+ var cmd = parseInt(_escNumber[0]);
+ if ((cmd == 0 || cmd == 2) && (_escNumber.length > 1) && (_escNumber[1] != '?')) {
+ if (obj.onTitleChange) { obj.onTitleChange(obj, obj.title = _escNumber[1]); }
+ }
+ }
+
+ function _ProcessEscapeHandler(code, args, argslen, mode) {
+ //console.log('process', code, args, mode);
+ if (mode == 1) {
+ switch (code) {
+ case 'l': // Hide the cursor
+ if (args[0] == 25) { _cursorVisible = false; }
+ break;
+ case 'h': // Show the cursor
+ if (args[0] == 25) { _cursorVisible = true; }
+ break;
+ }
+ } else if (mode == 0) {
+ var i;
+ switch (code) {
+ case 'c': // ResetDevice
+ // Reset
+ obj.TermResetScreen();
+ break;
+ case 'A': // Move cursor up n lines
+ if (argslen == 1) {
+ if (args[0] == 0) { _termy--; } else { _termy -= args[0]; }
+ if (_termy < 0) _termy = 0;
+ }
+ break;
+ case 'B': // Move cursor down n lines
+ if (argslen == 1) {
+ if (args[0] == 0) { _termy++; } else { _termy += args[0]; }
+ if (_termy > obj.height) _termy = obj.height;
+ }
+ break;
+ case 'C': // Move cursor right n lines
+ if (argslen == 1) {
+ if (args[0] == 0) { _termx++; } else { _termx += args[0]; }
+ if (_termx > obj.width) _termx = obj.width;
+ }
+ break;
+ case 'D': // Move cursor left n lines
+ if (argslen == 1) {
+ if (args[0] == 0) { _termx--; } else { _termx -= args[0]; }
+ if (_termx < 0) _termx = 0;
+ }
+ break;
+ case 'd': // Set cursor to line n
+ if (argslen == 1) {
+ _termy = args[0] - 1;
+ if (_termy > obj.height) _termy = obj.height;
+ if (_termy < 0) _termy = 0;
+ }
+ break;
+ case 'G': // Set cursor to col n
+ if (argslen == 1) {
+ _termx = args[0] - 1;
+ if (_termx < 0) _termx = 0;
+ if (_termx > (obj.width - 1)) _termx = (obj.width - 1);
+ }
+ break;
+ case 'P': // Delete X Character(s), default 1 char
+ var x = 1;
+ if (argslen == 1) { x = args[0]; }
+ for (i = _termx; i < obj.width - x; i++) { _tscreen[_termy][i] = _tscreen[_termy][i + x]; _scratt[_termy][i] = _scratt[_termy][i + x]; }
+ for (i = (obj.width - x); i < obj.width; i++) { _tscreen[_termy][i] = ' '; _scratt[_termy][i] = (7 << 6); }
+ break;
+ case 'L': // Insert X Line(s), default 1 char
+ var linecount = 1;
+ if (argslen == 1) { linecount = args[0]; }
+ if (linecount == 0) { linecount = 1; }
+ for (y = _scrollRegion[1]; y >= _termy + linecount; y--) {
+ _tscreen[y] = _tscreen[y - linecount];
+ _scratt[y] = _scratt[y - linecount];
+ }
+ for (y = _termy; y < _termy + linecount; y++) {
+ _tscreen[y] = [];
+ _scratt[y] = [];
+ for (x = 0; x < obj.width; x++) { _tscreen[y][x] = ' '; _scratt[y][x] = (7 << 6); }
+ }
+ break;
+ case 'J': // ClearScreen:
+ if (argslen == 1 && args[0] == 2) {
+ obj.TermClear((_TermCurrentBColor << 12) + (_TermCurrentFColor << 6)); // Erase entire screen
+ _termx = 0;
+ _termy = 0;
+ scrollBackBuffer = [];
+ }
+ else if (argslen == 0 || argslen == 1 && args[0] == 0) // Erase cursor down
+ {
+ _EraseCursorToEol();
+ for (i = _termy + 1; i < obj.height; i++) _EraseLine(i);
+ }
+ else if (argslen == 1 && args[0] == 1) // Erase cursor up
+ {
+ _EraseCursorToEol();
+ for (i = 0; i < _termy - 1; i++) _EraseLine(i);
+ }
+ break;
+ case 'H': // MoveCursor:
+ if (argslen == 2) {
+ if (args[0] < 1) args[0] = 1;
+ if (args[1] < 1) args[1] = 1;
+ if (args[0] > obj.height) args[0] = obj.height;
+ if (args[1] > obj.width) args[1] = obj.width;
+ _termy = args[0] - 1;
+ _termx = args[1] - 1;
+ } else {
+ _termy = 0;
+ _termx = 0;
+ }
+ break;
+ case 'm': // ScreenAttribs:
+ // Change attributes
+ for (i = 0; i < argslen; i++) {
+ if (!args[i] || args[i] == 0) {
+ // Reset Attributes
+ _TermCurrentBColor = 0;
+ _TermCurrentFColor = 7;
+ _TermCurrentReverse = 0;
+ }
+ else if (args[i] == 1) {
+ // Bright
+ if (_TermCurrentFColor < 8) _TermCurrentFColor += 8;
+ }
+ else if (args[i] == 2 || args[i] == 22) {
+ // Dim
+ if (_TermCurrentFColor >= 8) _TermCurrentFColor -= 8;
+ }
+ else if (args[i] == 7) {
+ // Set Reverse attribute true
+ _TermCurrentReverse = 2;
+ }
+ else if (args[i] == 27) {
+ // Set Reverse attribute false
+ _TermCurrentReverse = 0;
+ }
+ else if (args[i] >= 30 && args[i] <= 37) {
+ // Set Foreground Color
+ var bright = (_TermCurrentFColor >= 8);
+ _TermCurrentFColor = (args[i] - 30);
+ if (bright && _TermCurrentFColor <= 8) _TermCurrentFColor += 8;
+ }
+ else if (args[i] >= 40 && args[i] <= 47) {
+ // Set Background Color
+ _TermCurrentBColor = (args[i] - 40);
+ }
+ else if (args[i] >= 90 && args[i] <= 99) {
+ // Set Bright Foreground Color
+ _TermCurrentFColor = (args[i] - 82);
+ }
+ else if (args[i] >= 100 && args[i] <= 109) {
+ // Set Bright Background Color
+ _TermCurrentBColor = (args[i] - 92);
+ }
+ }
+ break;
+ case 'K': // EraseLine:
+ if (argslen == 0 || (argslen == 1 && (!args[0] || args[0] == 0))) {
+ _EraseCursorToEol(); // Erase from the cursor to the end of the line
+ } else if (argslen == 1) {
+ if (args[0] == 1) { // Erase from the beginning of the line to the cursor
+ _EraseBolToCursor();
+ } else if (args[0] == 2) { // Erase the line with the cursor
+ _EraseLine(_termy);
+ }
+ }
+ break;
+ case 'h': // EnableLineWrap:
+ _TermLineWrap = true;
+ break;
+ case 'l': // DisableLineWrap:
+ _TermLineWrap = false;
+ break;
+ case 'r': // Set the scroll region
+ if (argslen == 2) { _scrollRegion = [args[0] - 1, args[1] - 1]; }
+ if (_scrollRegion[0] < 0) { _scrollRegion[0] = 0; }
+ if (_scrollRegion[0] > (obj.height - 1)) { _scrollRegion[0] = (obj.height - 1); }
+ if (_scrollRegion[1] < 0) { _scrollRegion[1] = 0; }
+ if (_scrollRegion[1] > (obj.height - 1)) { _scrollRegion[1] = (obj.height - 1); }
+ if (_scrollRegion[0] > _scrollRegion[1]) { _scrollRegion[0] = _scrollRegion[1]; }
+ break;
+ case 'S': // Scroll up the scroll region X lines, default 1
+ var x = 1;
+ if (argslen == 1) { x = args[0] }
+ for (var y = _scrollRegion[0]; y <= _scrollRegion[1] - x; y++) {
+ for (var z = 0; z < obj.width; z++) { _tscreen[y][z] = _tscreen[y + x][z]; _scratt[y][z] = _scratt[y + x][z]; }
+ }
+ for (var y = _scrollRegion[1] - x + 1; y < _scrollRegion[1]; y++) {
+ for (var z = 0; z < obj.width; z++) { _tscreen[y][z] = ' '; _scratt[y][z] = (7 << 6); }
+ }
+ break;
+ case 'M': // Delete X lines, default 1
+ var x = 1;
+ if (argslen == 1) { x = args[0] }
+ for (var y = _termy; y <= _scrollRegion[1] - x; y++) {
+ for (var z = 0; z < obj.width; z++) { _tscreen[y][z] = _tscreen[y + x][z]; _scratt[y][z] = _scratt[y + x][z]; }
+ }
+ for (var y = _scrollRegion[1] - x + 1; y < _scrollRegion[1]; y++) {
+ for (var z = 0; z < obj.width; z++) { _tscreen[y][z] = ' '; _scratt[y][z] = (7 << 6); }
+ }
+ break;
+ case 'T': // Scroll down the scroll region X lines, default 1
+ var x = 1;
+ if (argslen == 1) { x = args[0] }
+ for (var y = _scrollRegion[1]; y > _scrollRegion[0] + x; y--) {
+ for (var z = 0; z < obj.width; z++) { _tscreen[y][z] = _tscreen[y - x][z]; _scratt[y][z] = _scratt[y - x][z]; }
+ }
+ for (var y = _scrollRegion[0] + x; y > _scrollRegion[0]; y--) {
+ for (var z = 0; z < obj.width; z++) { _tscreen[y][z] = ' '; _scratt[y][z] = (7 << 6); }
+ }
+ break;
+ case 'X': // Erase X characters, default 1
+ var x = 1, xx = _termx, yy = _termy;
+ if (argslen == 1) { x = args[0] }
+ while ((x > 0) && (yy < obj.height)) { _tscreen[yy][xx] = ' '; xx++; x--; if (xx >= obj.width) { xx = 0; yy++; } }
+ break;
+ default:
+ //if (code != '@') alert(code);
+ console.log('unknown terminal code', code, args, mode);
+ break;
+ }
+ }
+ }
+
+ obj.ProcessVt100String = function (str) {
+ for (var i = 0; i < str.length; i++) _ProcessVt100Char(String.fromCharCode(str.charCodeAt(i)));
+ }
+
+ // ###BEGIN###{Terminal-Enumation-All}
+ var AsciiToUnicode = [
+ 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
+ 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
+ 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
+ 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
+ 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00da,
+ 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
+ 0x2593, 0x2592, 0x2591, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
+ 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
+ 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
+ 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
+ 0x2568, 0x2564, 0x2565, 0x2568, 0x2558, 0x2552, 0x2553, 0x256b,
+ 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258b, 0x2590, 0x2580,
+ 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
+ 0x03c6, 0x03b8, 0x2126, 0x03b4, 0x221e, 0x00f8, 0x03b5, 0x220f,
+ 0x2261, 0x00b1, 0x2265, 0x2266, 0x2320, 0x2321, 0x00f7, 0x2248,
+ 0x00b0, 0x2022, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x220e, 0x00a0
+ ];
+
+ var AsciiToUnicodeIntel = [
+ 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
+ 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
+ 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
+ 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
+ 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00da,
+ 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ae, 0x00bb,
+ 0x2593, 0x2592, 0x2591, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
+ 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
+ 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
+ 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
+ 0x2568, 0x2564, 0x2565, 0x2568, 0x2558, 0x2552, 0x2553, 0x256b,
+ 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258b, 0x2590, 0x2580,
+ 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
+ 0x03c6, 0x03b8, 0x2126, 0x03b4, 0x221e, 0x00f8, 0x03b5, 0x220f,
+ 0x2261, 0x00b1, 0x2265, 0x2266, 0x2320, 0x2321, 0x00f7, 0x2248,
+ 0x00b0, 0x2022, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x220e, 0x00a0
+ ];
+ // ###END###{Terminal-Enumation-All}
+
+ // ###BEGIN###{Terminal-Enumation-ASCII}
+ var AsciiToUnicode = [
+ 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
+ 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
+ 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
+ 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
+ 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00da,
+ 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
+ 0x2593, 0x2592, 0x2591, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
+ 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
+ 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
+ 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
+ 0x2568, 0x2564, 0x2565, 0x2568, 0x2558, 0x2552, 0x2553, 0x256b,
+ 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258b, 0x2590, 0x2580,
+ 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
+ 0x03c6, 0x03b8, 0x2126, 0x03b4, 0x221e, 0x00f8, 0x03b5, 0x220f,
+ 0x2261, 0x00b1, 0x2265, 0x2266, 0x2320, 0x2321, 0x00f7, 0x2248,
+ 0x00b0, 0x2022, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x220e, 0x00a0
+ ];
+ // ###END###{Terminal-Enumation-ASCII}
+
+ // ###BEGIN###{Terminal-Enumation-Intel}
+ var AsciiToUnicodeIntel = [
+ 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
+ 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
+ 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
+ 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
+ 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00da,
+ 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ae, 0x00bb,
+ 0x2593, 0x2592, 0x2591, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
+ 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
+ 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
+ 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
+ 0x2568, 0x2564, 0x2565, 0x2568, 0x2558, 0x2552, 0x2553, 0x256b,
+ 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258b, 0x2590, 0x2580,
+ 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
+ 0x03c6, 0x03b8, 0x2126, 0x03b4, 0x221e, 0x00f8, 0x03b5, 0x220f,
+ 0x2261, 0x00b1, 0x2265, 0x2266, 0x2320, 0x2321, 0x00f7, 0x2248,
+ 0x00b0, 0x2022, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x220e, 0x00a0
+ ];
+ // ###END###{Terminal-Enumation-Intel}
+
+ function _ProcessVt100Char(c) {
+ if (c == '\0' || c.charCodeAt() == 7) return; // Ignore null & bell
+ var ch = c.charCodeAt();
+ //console.log('_ProcessVt100Char', ch, c);
+
+ // ###BEGIN###{Terminal-Enumation-All}
+ // UTF8 Terminal
+ if (obj.terminalEmulation == 1) {
+ // ANSI - Extended ASCII emulation.
+ if ((ch & 0x80) != 0) { c = String.fromCharCode(AsciiToUnicode[ch & 0x7F]); }
+ } else if (obj.terminalEmulation == 2) {
+ // ANSI - Intel Extended ASCII emulation.
+ if ((ch & 0x80) != 0) { c = String.fromCharCode(AsciiToUnicodeIntel[ch & 0x7F]); }
+ }
+ // ###END###{Terminal-Enumation-All}
+
+ // ###BEGIN###{Terminal-Enumation-ASCII}
+ // ANSI - Extended ASCII emulation.
+ //if ((ch & 0x80) != 0) { c = String.fromCharCode(AsciiToUnicode[ch & 0x7F]); }
+ // ###END###{Terminal-Enumation-ASCII}
+
+ // ###BEGIN###{Terminal-Enumation-Intel}
+ // ANSI - Intel Extended ASCII emulation.
+ //if ((ch & 0x80) != 0) { c = String.fromCharCode(AsciiToUnicodeIntel[ch & 0x7F]); }
+ // ###END###{Terminal-Enumation-Intel}
+
+ //if (ch < 32 && ch != 10 && ch != 13) alert(ch);
+ switch (ch) {
+ case 16: { c = ' '; break; } // This is an odd char that show up on Intel BIOS's.
+ case 24: { c = '↑'; break; }
+ case 25: { c = '↓'; break; }
+ }
+
+ if (_termx > obj.width) _termx = obj.width;
+ if (_termy > (obj.height - 1)) _termy = (obj.height - 1);
+
+ switch (c) {
+ case '\b': // Backspace
+ if (_termx > 0) {
+ _termx--;
+ if (_backSpaceErase) { _TermDrawChar(' '); }
+ }
+ break;
+ case '\t': // tab
+ var tab = 8 - (_termx % 8)
+ for (var x = 0; x < tab; x++) _ProcessVt100Char(" ");
+ break;
+ case '\n': // Linefeed
+ _termy++;
+ if (_termy > _scrollRegion[1]) {
+ // Move everything up one line
+ obj.recordLineTobackBuffer(0);
+ _TermMoveUp(1);
+ _termy = _scrollRegion[1];
+ }
+ if (obj.lineFeed = '\r') { _termx = 0; } // *** If we are in Linux mode, \n will also return the cursor to the first col
+ break;
+ case '\r': // Carriage Return
+ _termx = 0;
+ break;
+ default:
+ if (_termx >= obj.width) {
+ _termx = 0;
+ if (_TermLineWrap) { _termy++; }
+ if (_termy >= (obj.height - 1)) { _TermMoveUp(1); _termy = (obj.height - 1); }
+ }
+ _TermDrawChar(c);
+ _termx++;
+ break;
+ }
+ }
+
+ function _TermDrawChar(c) {
+ _tscreen[_termy][_termx] = c;
+ _scratt[_termy][_termx] = (_TermCurrentFColor << 6) + (_TermCurrentBColor << 12) + _TermCurrentReverse;
+ }
+
+ obj.TermClear = function(TermColor) {
+ for (var y = 0; y < obj.height; y++) {
+ for (var x = 0; x < obj.width; x++) {
+ _tscreen[y][x] = ' ';
+ _scratt[y][x] = TermColor;
+ }
+ }
+ scrollBackBuffer = [];
+ }
+
+ obj.TermResetScreen = function () {
+ _TermCurrentReverse = 0;
+ _TermCurrentFColor = 7;
+ _TermCurrentBColor = 0;
+ _TermLineWrap = _cursorVisible = true;
+ _termx = _termy = 0;
+ _backSpaceErase = false;
+ _scrollRegion = [0, (obj.height - 1)];
+ _altKeypadMode = false;
+ obj.TermClear(7 << 6);
+ // ###BEGIN###{Terminal-Enumation-UTF8}
+ //utf8decodeBuffer = '';
+ // ###END###{Terminal-Enumation-UTF8}
+ // ###BEGIN###{Terminal-Enumation-All}
+ utf8decodeBuffer = '';
+ // ###END###{Terminal-Enumation-All}
+ }
+
+ function _EraseCursorToEol() {
+ var t = (_TermCurrentFColor << 6) + (_TermCurrentBColor << 12) + _TermCurrentReverse;
+ for (var x = _termx; x < obj.width; x++) {
+ _tscreen[_termy][x] = ' ';
+ _scratt[_termy][x] = t;
+ }
+ }
+
+ function _EraseBolToCursor() {
+ var t = (_TermCurrentFColor << 6) + (_TermCurrentBColor << 12) + _TermCurrentReverse;
+ for (var x = 0; x < _termx; x++) {
+ _tscreen[_termy][x] = ' ';
+ _scratt[_termy][x] = t;
+ }
+ }
+
+ function _EraseLine(line) {
+ var t = (_TermCurrentFColor << 6) + (_TermCurrentBColor << 12) + _TermCurrentReverse;
+ for (var x = 0; x < obj.width; x++) {
+ _tscreen[line][x] = ' ';
+ _scratt[line][x] = t;
+ }
+ }
+
+ obj.TermSendKeys = function (keys) { if (obj.debugmode == 2) { console.log("TSend(" + keys.length + "): " + rstr2hex(keys), keys); } if (obj.parent) { obj.parent.Send(keys); } }
+ obj.TermSendKey = function (key) { if (obj.debugmode == 2) { console.log("TSend(1): " + rstr2hex(String.fromCharCode(key)), key); } if (obj.parent) { obj.parent.Send(String.fromCharCode(key)); } }
+
+ function _TermMoveUp(linecount) {
+ var x, y;
+ for (y = _scrollRegion[0]; y <= _scrollRegion[1] - linecount; y++) {
+ _tscreen[y] = _tscreen[y + linecount];
+ _scratt[y] = _scratt[y + linecount];
+ }
+ for (y = _scrollRegion[1] - linecount + 1; y <= _scrollRegion[1]; y++) {
+ _tscreen[y] = [];
+ _scratt[y] = [];
+ for (x = 0; x < obj.width; x++) {
+ _tscreen[y][x] = ' ';
+ _scratt[y][x] = (7 << 6);
+ }
+ }
+ }
+
+ obj.TermHandleKeys = function (e) {
+ if (!e.ctrlKey) {
+ if (e.which == 127) obj.TermSendKey(8);
+ else if (e.which == 13) { obj.TermSendKeys(obj.lineFeed); }
+ else if (e.which != 0) obj.TermSendKey(e.which);
+ return false;
+ }
+ if (e.preventDefault) e.preventDefault();
+ if (e.stopPropagation) e.stopPropagation();
+ }
+
+ obj.TermHandleKeyUp = function (e) {
+ if ((e.which != 8) && (e.which != 32) && (e.which != 9)) return true;
+ if (e.preventDefault) e.preventDefault();
+ if (e.stopPropagation) e.stopPropagation();
+ return false;
+ }
+
+ obj.TermHandleKeyDown = function (e) {
+ if ((e.which >= 65) && (e.which <= 90) && (e.ctrlKey == true)) {
+ obj.TermSendKey(e.which - 64);
+ if (e.preventDefault) e.preventDefault();
+ if (e.stopPropagation) e.stopPropagation();
+ return;
+ }
+ if (e.which == 27) { obj.TermSendKeys(String.fromCharCode(27)); return true; }; // ESC
+
+ if (_altKeypadMode == true) {
+ if (e.which == 37) { obj.TermSendKeys(String.fromCharCode(27, 79, 68)); return true; }; // Left
+ if (e.which == 38) { obj.TermSendKeys(String.fromCharCode(27, 79, 65)); return true; }; // Up
+ if (e.which == 39) { obj.TermSendKeys(String.fromCharCode(27, 79, 67)); return true; }; // Right
+ if (e.which == 40) { obj.TermSendKeys(String.fromCharCode(27, 79, 66)); return true; }; // Down
+ } else {
+ if (e.which == 37) { obj.TermSendKeys(String.fromCharCode(27, 91, 68)); return true; }; // Left
+ if (e.which == 38) { obj.TermSendKeys(String.fromCharCode(27, 91, 65)); return true; }; // Up
+ if (e.which == 39) { obj.TermSendKeys(String.fromCharCode(27, 91, 67)); return true; }; // Right
+ if (e.which == 40) { obj.TermSendKeys(String.fromCharCode(27, 91, 66)); return true; }; // Down
+ }
+
+ if (e.which == 33) { obj.TermSendKeys(String.fromCharCode(27, 91, 53, 126)); return true; }; // PageUp
+ if (e.which == 34) { obj.TermSendKeys(String.fromCharCode(27, 91, 54, 126)); return true; }; // PageDown
+ if (e.which == 35) { obj.TermSendKeys(String.fromCharCode(27, 91, 70)); return true; }; // End
+ if (e.which == 36) { obj.TermSendKeys(String.fromCharCode(27, 91, 72)); return true; }; // Home
+ if (e.which == 45) { obj.TermSendKeys(String.fromCharCode(27, 91, 50, 126)); return true; }; // Insert
+ if (e.which == 46) { obj.TermSendKeys(String.fromCharCode(27, 91, 51, 126)); return true; }; // Delete
+
+ if (e.which == 9) { obj.TermSendKeys("\t"); if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return true; }; // TAB
+
+ // F1 to F12 keys
+ // ###BEGIN###{Terminal-FxEnumation-All}
+ var fx0 = [80, 81, 119, 120, 116, 117, 113, 114, 112, 77];
+ var fx1 = [49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 33, 64];
+ var fx2 = [80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91];
+ if (e.which > 111 & e.which < 124 && e.repeat == false) { // F1 to F12 keys
+ if (obj.fxEmulation == 0 && e.which < 122) { obj.TermSendKeys(String.fromCharCode(27, 91, 79, fx0[e.which - 112])); return true; } // 'Intel (F10 = ESC+[OM)'
+ if (obj.fxEmulation == 1) { obj.TermSendKeys(String.fromCharCode(27, fx1[e.which - 112])); return true; } // 'Alternate (F10 = ESC+0)'
+ if (obj.fxEmulation == 2) { obj.TermSendKeys(String.fromCharCode(27, 79, fx2[e.which - 112])); return true; } // 'VT100+ (F10 = ESC+[OY)'
+ }
+ // ###END###{Terminal-FxEnumation-All}
+ // ###BEGIN###{Terminal-FxEnumation-Intel}
+ var fx0 = [80, 81, 119, 120, 116, 117, 113, 114, 112, 77];
+ if (e.which > 111 & e.which < 122 && e.repeat == false) { obj.TermSendKeys(String.fromCharCode(27, 91, 79, fx0[e.which - 112])); return true; } // 'Intel (F10 = ESC+[OM)'
+ // ###END###{Terminal-FxEnumation-Intel}
+ // ###BEGIN###{Terminal-FxEnumation-Alternate}
+ var fx1 = [49, 50, 51, 52, 53, 54, 55, 56, 57, 48, 33, 64];
+ if (e.which > 111 & e.which < 124 && e.repeat == false) { obj.TermSendKeys(String.fromCharCode(27, fx1[e.which - 112])); return true; } // 'Alternate (F10 = ESC+0)'
+ // ###END###{Terminal-FxEnumation-Alternate}
+ // ###BEGIN###{Terminal-FxEnumation-VT100Plus}
+ var fx2 = [80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91];
+ if (e.which > 111 & e.which < 124 && e.repeat == false) { obj.TermSendKeys(String.fromCharCode(27, 79, fx2[e.which - 112])); return true; } // 'VT100+ (F10 = ESC+[OY)'
+ // ###END###{Terminal-FxEnumation-VT100Plus}
+
+ if (e.which != 8 && e.which != 32 && e.which != 9) return true;
+ obj.TermSendKey(e.which);
+ if (e.preventDefault) e.preventDefault();
+ if (e.stopPropagation) e.stopPropagation();
+ return false;
+ }
+
+ obj.recordLineTobackBuffer = function(y) {
+ var closetag = '', buf = '';
+ var r = obj.TermDrawLine(buf, y, closetag);
+ buf = r[0];
+ closetag = r[1];
+ scrollBackBuffer.push(buf + closetag + ' ');
+ }
+
+ obj.TermDrawLine = function (buf, y, closetag) {
+ var newat, c, oldat = 1, x1, x2;
+ for (var x = 0; x < obj.width; ++x) {
+ newat = _scratt[y][x];
+ if (_termx == x && _termy == y && _cursorVisible) { newat |= _VTREVERSE; } // If this is the cursor location, reverse the color.
+ if (newat != oldat) {
+ buf += closetag;
+ closetag = '';
+ x1 = 6; x2 = 12;
+ if (newat & _VTREVERSE) { x1 = 12; x2 = 6; }
+ buf += '';
+ closetag = " " + closetag;
+ oldat = newat;
+ }
+
+ c = _tscreen[y][x];
+ switch (c) {
+ case '&': buf += '&'; break;
+ case '<': buf += '<'; break;
+ case '>': buf += '>'; break;
+ case ' ': buf += ' '; break;
+ default: buf += c; break;
+ }
+ }
+ return [buf, closetag];
+ }
+
+ obj.TermDraw = function() {
+ var closetag = '', buf = '';
+ for (var y = 0; y < obj.height; ++y) {
+ var r = obj.TermDrawLine(buf, y, closetag);
+ buf = r[0];
+ closetag = r[1];
+ if (y != (obj.height - 1)) buf += ' ';
+ }
+
+ if (scrollBackBuffer.length > 800) { scrollBackBuffer = scrollBackBuffer.slice(scrollBackBuffer.length - 800); }
+ var backbuffer = scrollBackBuffer.join('');
+ obj.DivElement.innerHTML = "" + backbuffer + buf + closetag + " ";
+ obj.DivElement.scrollTop = obj.DivElement.scrollHeight;
+ //if (obj.heightLock == 0) { setTimeout(obj.TermLockHeight, 10); }
+ }
+
+ /*
+ obj.TermLockHeight = function () {
+ obj.heightLock = obj.DivElement.clientHeight;
+ obj.DivElement.style['height'] = obj.DivElement.parentNode.style['height'] = obj.heightLock + 'px';
+ obj.DivElement.style['overflow-y'] = 'scroll';
+ }
+ */
+
+ obj.TermInit = function () { obj.TermResetScreen(); }
+
+ //obj.heightLock = 0;
+ //obj.DivElement.style['height'] = '';
+ if ((options != null) && (options.width != null) && (options.height != null)) { obj.Init(options.width, options.height); } else { obj.Init(); }
+ return obj;
+}
\ No newline at end of file
diff --git a/amt-wsman-0.2.0.js b/amt-wsman-0.2.0.js
new file mode 100644
index 0000000..7426aa9
--- /dev/null
+++ b/amt-wsman-0.2.0.js
@@ -0,0 +1,336 @@
+/**
+* @description Intel(r) AMT WSMAN Stack
+* @author Ylian Saint-Hilaire
+* @version v0.2.0
+*/
+
+// Construct a MeshServer object
+var WsmanStackCreateService = function (host, port, user, pass, tls, extra) {
+ var obj = {};
+ //obj.onDebugMessage = null; // Set to a function if you want to get debug messages.
+ obj.NextMessageId = 1; // Next message number, used to label WSMAN calls.
+ obj.Address = '/wsman';
+ obj.comm = CreateWsmanComm(host, port, user, pass, tls, extra);
+
+ obj.PerformAjax = function (postdata, callback, tag, pri, namespaces) {
+ if (namespaces == null) namespaces = '';
+ obj.comm.PerformAjax('' + postdata, function (data, status, tag) {
+ if (status != 200) { callback(obj, null, { Header: { HttpError: status } }, status, tag); return; }
+ var wsresponse = obj.ParseWsman(data);
+ if (!wsresponse || wsresponse == null) { callback(obj, null, { Header: { HttpError: status } }, 601, tag); } else { callback(obj, wsresponse.Header["ResourceURI"], wsresponse, 200, tag); }
+ }, tag, pri);
+ }
+
+ // Private method
+ //obj.Debug = function (msg) { /*console.log(msg);*/ }
+
+ // Cancel all pending queries with given status
+ obj.CancelAllQueries = function (s) { obj.comm.CancelAllQueries(s); }
+
+ // Get the last element of a URI string
+ obj.GetNameFromUrl = function (resuri) {
+ var x = resuri.lastIndexOf("/");
+ return (x == -1)?resuri:resuri.substring(x + 1);
+ }
+
+ // Perform a WSMAN Subscribe operation
+ obj.ExecSubscribe = function (resuri, delivery, url, callback, tag, pri, selectors, opaque, user, pass) {
+ var digest = "", digest2 = "", opaque = "";
+ if (user != null && pass != null) { digest = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken ' + user + ' ' + pass + ' '; digest2 = ' '; }
+ if (opaque != null) { opaque = '' + opaque + ' '; }
+ if (delivery == 'PushWithAck') { delivery = 'dmtf.org/wbem/wsman/1/wsman/PushWithAck'; } else if (delivery == 'Push') { delivery = 'xmlsoap.org/ws/2004/08/eventing/DeliveryModes/Push'; }
+ var data = "http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe " + obj.Address + " " + resuri + " " + (obj.NextMessageId++) + " http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous " + _PutObjToSelectorsXml(selectors) + digest + '' + url + ' ' + opaque + ' ' + digest2 + ' ';
+ obj.PerformAjax(data + " ", callback, tag, pri, 'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:m="http://x.com"');
+ }
+
+ // Perform a WSMAN UnSubscribe operation
+ obj.ExecUnSubscribe = function (resuri, callback, tag, pri, selectors) {
+ var data = "http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe" + obj.Address + " " + resuri + " " + (obj.NextMessageId++) + " http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous " + _PutObjToSelectorsXml(selectors) + ' ';
+ obj.PerformAjax(data + "", callback, tag, pri, 'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing"');
+ }
+
+ // Perform a WSMAN PUT operation
+ obj.ExecPut = function (resuri, putobj, callback, tag, pri, selectors) {
+ var data = "http://schemas.xmlsoap.org/ws/2004/09/transfer/Put" + obj.Address + " " + resuri + " " + (obj.NextMessageId++) + " http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous PT60.000S " + _PutObjToSelectorsXml(selectors) + '' + _PutObjToBodyXml(resuri, putobj);
+ obj.PerformAjax(data + "", callback, tag, pri);
+ }
+
+ // Perform a WSMAN CREATE operation
+ obj.ExecCreate = function (resuri, putobj, callback, tag, pri, selectors) {
+ var objname = obj.GetNameFromUrl(resuri);
+ var data = "http://schemas.xmlsoap.org/ws/2004/09/transfer/Create" + obj.Address + " " + resuri + " " + (obj.NextMessageId++) + " http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous PT60S " + _PutObjToSelectorsXml(selectors) + "";
+ for (var n in putobj) { data += "" + putobj[n] + " " }
+ obj.PerformAjax(data + " ", callback, tag, pri);
+ }
+
+ // Perform a WSMAN DELETE operation
+ obj.ExecDelete = function (resuri, putobj, callback, tag, pri) {
+ var data = "http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete" + obj.Address + " " + resuri + " " + (obj.NextMessageId++) + " http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous PT60S " + _PutObjToSelectorsXml(putobj) + " ";
+ obj.PerformAjax(data, callback, tag, pri);
+ }
+
+ // Perform a WSMAN GET operation
+ obj.ExecGet = function (resuri, callback, tag, pri) {
+ obj.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Get" + obj.Address + " " + resuri + " " + (obj.NextMessageId++) + " http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous PT60S ", callback, tag, pri);
+ }
+
+ // Perform a WSMAN method call operation
+ obj.ExecMethod = function (resuri, method, args, callback, tag, pri, selectors) {
+ var argsxml = "";
+ for (var i in args) { if (args[i] != null) { if (Array.isArray(args[i])) { for (var x in args[i]) { argsxml += "" + args[i][x] + " "; } } else { argsxml += "" + args[i] + " "; } } }
+ obj.ExecMethodXml(resuri, method, argsxml, callback, tag, pri, selectors);
+ }
+
+ // Perform a WSMAN method call operation. The arguments are already formatted in XML.
+ obj.ExecMethodXml = function (resuri, method, argsxml, callback, tag, pri, selectors) {
+ obj.PerformAjax(resuri + "/" + method + "" + obj.Address + " " + resuri + " " + (obj.NextMessageId++) + " http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous PT60S " + _PutObjToSelectorsXml(selectors) + "
" + argsxml + " ", callback, tag, pri);
+ }
+
+ // Perform a WSMAN ENUM operation
+ obj.ExecEnum = function (resuri, callback, tag, pri) {
+ obj.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate" + obj.Address + " " + resuri + " " + (obj.NextMessageId++) + " http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous PT60S ", callback, tag, pri);
+ }
+
+ // Perform a WSMAN PULL operation
+ obj.ExecPull = function (resuri, enumctx, callback, tag, pri) {
+ obj.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Pull" + obj.Address + " " + resuri + " " + (obj.NextMessageId++) + " http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous PT60S " + enumctx + " ", callback, tag, pri); // --999 99999 --
+ }
+
+ // Private method
+ obj.ParseWsman = function (xml) {
+ try {
+ if (!xml.childNodes) xml = _turnToXml(xml);
+ var r = { Header:{} }, header = xml.getElementsByTagName("Header")[0], t;
+ if (!header) header = xml.getElementsByTagName("a:Header")[0];
+ if (!header) return null;
+ for (var i = 0; i < header.childNodes.length; i++) {
+ var child = header.childNodes[i];
+ r.Header[child.localName] = child.textContent;
+ }
+ var body = xml.getElementsByTagName("Body")[0];
+ if (!body) body = xml.getElementsByTagName("a:Body")[0];
+ if (!body) return null;
+ if (body.childNodes.length > 0) {
+ t = body.childNodes[0].localName;
+ if (t.indexOf("_OUTPUT") == t.length - 7) { t = t.substring(0, t.length - 7); }
+ r.Header['Method'] = t;
+ r.Body = _ParseWsmanRec(body.childNodes[0]);
+ }
+ return r;
+ } catch (e) {
+ console.log("Unable to parse XML: " + xml);
+ return null;
+ }
+ }
+
+ // Private method
+ function _ParseWsmanRec(node) {
+ var data, r = {};
+ for (var i = 0; i < node.childNodes.length; i++) {
+ var child = node.childNodes[i];
+ if ((child.childElementCount == null) || (child.childElementCount == 0)) { data = child.textContent; } else { data = _ParseWsmanRec(child); }
+ if (data == 'true') data = true; // Convert 'true' into true
+ if (data == 'false') data = false; // Convert 'false' into false
+ if ((parseInt(data) + '') === data) data = parseInt(data); // Convert integers
+
+ var childObj = data;
+ if ((child.attributes != null) && (child.attributes.length > 0)) {
+ childObj = { 'Value': data };
+ for(var j = 0; j < child.attributes.length; j++) {
+ childObj['@' + child.attributes[j].name] = child.attributes[j].value;
+ }
+ }
+
+ if (r[child.localName] instanceof Array) { r[child.localName].push(childObj); }
+ else if (r[child.localName] == null) { r[child.localName] = childObj; }
+ else { r[child.localName] = [r[child.localName], childObj]; }
+ }
+ return r;
+ }
+
+ function _PutObjToBodyXml(resuri, putObj) {
+ if (!resuri || putObj == null) return '';
+ var objname = obj.GetNameFromUrl(resuri);
+ var result = '';
+
+ for (var prop in putObj) {
+ if (!putObj.hasOwnProperty(prop) || prop.indexOf('__') === 0 || prop.indexOf('@') === 0) continue;
+ if (putObj[prop] == null || typeof putObj[prop] === 'function') continue;
+ if (typeof putObj[prop] === 'object' && putObj[prop]['ReferenceParameters']) {
+ result += '' + putObj[prop].Address + ' ' + putObj[prop]['ReferenceParameters']["ResourceURI"] + ' ';
+ var selectorArray = putObj[prop]['ReferenceParameters']['SelectorSet']['Selector'];
+ if (Array.isArray(selectorArray)) {
+ for (var i=0; i< selectorArray.length; i++) {
+ result += '' + selectorArray[i]['Value'] + ' ';
+ }
+ }
+ else {
+ result += '' + selectorArray['Value'] + ' ';
+ }
+ result += ' ';
+ }
+ else {
+ if (Array.isArray(putObj[prop])) {
+ for (var i = 0; i < putObj[prop].length; i++) {
+ result += '' + putObj[prop][i].toString() + ' ';
+ }
+ } else {
+ result += '' + putObj[prop].toString() + ' ';
+ }
+ }
+ }
+
+ result += ' ';
+ return result;
+ }
+
+ /*
+ convert
+ { @Name: 'InstanceID', @AttrName: 'Attribute Value'}
+ into
+ ' Name="InstanceID" AttrName="Attribute Value" '
+ */
+ function _ObjectToXmlAttributes(objWithAttributes) {
+ if(!objWithAttributes) return '';
+ var result = '';
+ for (var propName in objWithAttributes) {
+ if (!objWithAttributes.hasOwnProperty(propName) || propName.indexOf('@') !== 0) continue;
+ result += ' ' + propName.substring(1) + '="' + objWithAttributes[propName] + '"';
+ }
+ return result;
+ }
+
+ function _PutObjToSelectorsXml(selectorSet) {
+ if (!selectorSet) return '';
+ if (typeof selectorSet == 'string') return selectorSet;
+ if (selectorSet['InstanceID']) return "" + selectorSet['InstanceID'] + " ";
+ var result = '';
+ for(var propName in selectorSet) {
+ if (!selectorSet.hasOwnProperty(propName)) continue;
+ result += '';
+ if (selectorSet[propName]['ReferenceParameters']) {
+ result += '';
+ result += '' + selectorSet[propName]['Address'] + ' ' + selectorSet[propName]['ReferenceParameters']['ResourceURI'] + ' ';
+ var selectorArray = selectorSet[propName]['ReferenceParameters']['SelectorSet']['Selector'];
+ if (Array.isArray(selectorArray)) {
+ for (var i = 0; i < selectorArray.length; i++) {
+ result += '' + selectorArray[i]['Value'] + ' ';
+ }
+ }
+ else {
+ result += '' + selectorArray['Value'] + ' ';
+ }
+ result += ' ';
+ } else {
+ result += selectorSet[propName];
+ }
+ result += ' ';
+ }
+ result += ' ';
+ return result;
+ }
+
+ function _turnToXml(text) {
+ // ###BEGIN###{!Mode-MeshCentral2}
+ // NodeJS detection
+ var isNode = new Function("try {return this===global;}catch(e){return false;}");
+ if (isNode()) {
+ var XDOMParser = require('xmldom').DOMParser;
+ return new XDOMParser().parseFromString(text, "text/xml");
+ }
+ // ###END###{!Mode-MeshCentral2}
+ if (window.DOMParser) {
+ return new DOMParser().parseFromString(text, "text/xml");
+ } else {
+ // Internet Explorer
+ var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
+ xmlDoc.async = false;
+ xmlDoc.loadXML(text);
+ return xmlDoc;
+ }
+ }
+
+ /*
+ // This is a drop-in replacement to _turnToXml() that works without xml parser dependency.
+ Object.defineProperty(Array.prototype, "peek", { value: function () { return (this.length > 0 ? this[this.length - 1] : null); } });
+ function _treeBuilder() {
+ this.tree = [];
+ this.push = function (element) { this.tree.push(element); };
+ this.pop = function () { var element = this.tree.pop(); if (this.tree.length > 0) { var x = this.tree.peek(); x.childNodes.push(element); x.childElementCount = x.childNodes.length; } return (element); };
+ this.peek = function () { return (this.tree.peek()); }
+ this.addNamespace = function (prefix, namespace) { this.tree.peek().nsTable[prefix] = namespace; if (this.tree.peek().attributes.length > 0) { for (var i = 0; i < this.tree.peek().attributes; ++i) { var a = this.tree.peek().attributes[i]; if (prefix == '*' && a.name == a.localName) { a.namespace = namespace; } else if (prefix != '*' && a.name != a.localName) { var pfx = a.name.split(':')[0]; if (pfx == prefix) { a.namespace = namespace; } } } } }
+ this.getNamespace = function (prefix) { for (var i = this.tree.length - 1; i >= 0; --i) { if (this.tree[i].nsTable[prefix] != null) { return (this.tree[i].nsTable[prefix]); } } return null; }
+ }
+ function _turnToXml(text) { if (text == null) return null; return ({ childNodes: [_turnToXmlRec(text)], getElementsByTagName: _getElementsByTagName, getChildElementsByTagName: _getChildElementsByTagName, getElementsByTagNameNS: _getElementsByTagNameNS }); }
+ function _getElementsByTagNameNS(ns, name) { var ret = []; _xmlTraverseAllRec(this.childNodes, function (node) { if (node.localName == name && (node.namespace == ns || ns == '*')) { ret.push(node); } }); return ret; }
+ function _getElementsByTagName(name) { var ret = []; _xmlTraverseAllRec(this.childNodes, function (node) { if (node.localName == name) { ret.push(node); } }); return ret; }
+ function _getChildElementsByTagName(name) { var ret = []; if (this.childNodes != null) { for (var node in this.childNodes) { if (this.childNodes[node].localName == name) { ret.push(this.childNodes[node]); } } } return (ret); }
+ function _getChildElementsByTagNameNS(ns, name) { var ret = []; if (this.childNodes != null) { for (var node in this.childNodes) { if (this.childNodes[node].localName == name && (ns == '*' || this.childNodes[node].namespace == ns)) { ret.push(this.childNodes[node]); } } } return (ret); }
+ function _xmlTraverseAllRec(nodes, func) { for (var i in nodes) { func(nodes[i]); if (nodes[i].childNodes) { _xmlTraverseAllRec(nodes[i].childNodes, func); } } }
+ function _turnToXmlRec(text) {
+ var elementStack = new _treeBuilder(), lastElement = null, x1 = text.split('<'), ret = [], element = null, currentElementName = null;
+ for (var i in x1) {
+ var x2 = x1[i].split('>'), x3 = x2[0].split(' '), elementName = x3[0];
+ if ((elementName.length > 0) && (elementName[0] != '?')) {
+ if (elementName[0] != '/') {
+ var attributes = [], localName, localname2 = elementName.split(' ')[0].split(':'), localName = (localname2.length > 1) ? localname2[1] : localname2[0];
+ Object.defineProperty(attributes, "get",
+ {
+ value: function () {
+ if (arguments.length == 1) {
+ for (var a in this) { if (this[a].name == arguments[0]) { return (this[a]); } }
+ }
+ else if (arguments.length == 2) {
+ for (var a in this) { if (this[a].name == arguments[1] && (arguments[0] == '*' || this[a].namespace == arguments[0])) { return (this[a]); } }
+ }
+ else {
+ throw ('attributes.get(): Invalid number of parameters');
+ }
+ }
+ });
+ elementStack.push({ name: elementName, localName: localName, getChildElementsByTagName: _getChildElementsByTagName, getElementsByTagNameNS: _getElementsByTagNameNS, getChildElementsByTagNameNS: _getChildElementsByTagNameNS, attributes: attributes, childNodes: [], nsTable: {} });
+ // Parse Attributes
+ if (x3.length > 0) {
+ var skip = false;
+ for (var j in x3) {
+ if (x3[j] == '/') {
+ // This is an empty Element
+ elementStack.peek().namespace = elementStack.peek().name == elementStack.peek().localName ? elementStack.getNamespace('*') : elementStack.getNamespace(elementStack.peek().name.substring(0, elementStack.peek().name.indexOf(':')));
+ elementStack.peek().textContent = '';
+ lastElement = elementStack.pop();
+ skip = true;
+ break;
+ }
+ var k = x3[j].indexOf('=');
+ if (k > 0) {
+ var attrName = x3[j].substring(0, k);
+ var attrValue = x3[j].substring(k + 2, x3[j].length - 1);
+ var attrNS = elementStack.getNamespace('*');
+
+ if (attrName == 'xmlns') {
+ elementStack.addNamespace('*', attrValue);
+ attrNS = attrValue;
+ } else if (attrName.startsWith('xmlns:')) {
+ elementStack.addNamespace(attrName.substring(6), attrValue);
+ } else {
+ var ax = attrName.split(':');
+ if (ax.length == 2) { attrName = ax[1]; attrNS = elementStack.getNamespace(ax[0]); }
+ }
+ var x = { name: attrName, value: attrValue }
+ if (attrNS != null) x.namespace = attrNS;
+ elementStack.peek().attributes.push(x);
+ }
+ }
+ if (skip) { continue; }
+ }
+ elementStack.peek().namespace = elementStack.peek().name == elementStack.peek().localName ? elementStack.getNamespace('*') : elementStack.getNamespace(elementStack.peek().name.substring(0, elementStack.peek().name.indexOf(':')));
+ if (x2[1]) { elementStack.peek().textContent = x2[1]; }
+ } else { lastElement = elementStack.pop(); }
+ }
+ }
+ return lastElement;
+ }
+ */
+
+ return obj;
+}
diff --git a/amt-wsman-ajax-0.2.0.js b/amt-wsman-ajax-0.2.0.js
new file mode 100644
index 0000000..7cca880
--- /dev/null
+++ b/amt-wsman-ajax-0.2.0.js
@@ -0,0 +1,95 @@
+/**
+* @description WSMAN communication using browser AJAX
+* @author Ylian Saint-Hilaire
+* @version v0.2.0c
+*/
+
+// Construct a WSMAN communication object
+var CreateWsmanComm = function (url) {
+ var obj = {};
+ obj.PendingAjax = []; // List of pending AJAX calls. When one frees up, another will start.
+ obj.ActiveAjaxCount = 0; // Number of currently active AJAX calls
+ obj.MaxActiveAjaxCount = 1; // Maximum number of activate AJAX calls at the same time.
+ obj.FailAllError = 0; // Set this to non-zero to fail all AJAX calls with that error status, 999 causes responses to be silent.
+ obj.Url = url;
+
+ // Private method
+ // pri = priority, if set to 1, the call is high priority and put on top of the stack.
+ obj.PerformAjax = function (postdata, callback, tag, pri, url, action) {
+ if ((obj.ActiveAjaxCount == 0 || ((obj.ActiveAjaxCount < obj.MaxActiveAjaxCount) && (obj.challengeParams != null))) && obj.PendingAjax.length == 0) {
+ // There are no pending AJAX calls, perform the call now.
+ obj.PerformAjaxEx(postdata, callback, tag, url, action);
+ } else {
+ // If this is a high priority call, put this call in front of the array, otherwise put it in the back.
+ if (pri == 1) { obj.PendingAjax.unshift([postdata, callback, tag, url, action]); } else { obj.PendingAjax.push([postdata, callback, tag, url, action]); }
+ }
+ }
+
+ // Private method
+ obj.PerformNextAjax = function () {
+ if (obj.ActiveAjaxCount >= obj.MaxActiveAjaxCount || obj.PendingAjax.length == 0) return;
+ var x = obj.PendingAjax.shift();
+ obj.PerformAjaxEx(x[0], x[1], x[2], x[3], x[4]);
+ obj.PerformNextAjax();
+ }
+
+ // Private method
+ obj.PerformAjaxEx = function (postdata, callback, tag, url, action) {
+ if (obj.FailAllError != 0) { if (obj.FailAllError != 999) { obj.gotNextMessagesError({ status: obj.FailAllError }, 'error', null, [postdata, callback, tag]); } return; }
+ // console.log("SEND: " + postdata); // DEBUG
+
+ // We are in a AJAX browser environment
+ obj.ActiveAjaxCount++;
+ if (!postdata) { postdata = ''; }
+ var xdr = null; // TODO: See if we should re-use this object and if we do, when should we do it.
+ try { xdr = new XDomainRequest(); } catch (e) { }
+ if (!xdr) xdr = new XMLHttpRequest();
+ xdr.open(action ? action : "POST", url ? url : obj.Url);
+ xdr.timeout = 15000;
+ xdr.onload = function () { obj.gotNextMessages(xdr.responseText, 'success', xdr, [postdata, callback, tag]); };
+ xdr.onerror = function () { obj.gotNextMessagesError(xdr, 'error', null, [postdata, callback, tag]); };
+ xdr.ontimeout = function () { obj.gotNextMessagesError(xdr, 'error', null, [postdata, callback, tag]); };
+ //xdr.send(postdata); // Works for text only, no binary.
+
+ // Send POST body, this work with binary.
+ if (urlvars && urlvars['wsmantrace']) { console.log("WSMAN-SEND(" + postdata.length + "): " + postdata); }
+ var b = new Uint8Array(postdata.length);
+ for (var i = 0; i < postdata.length; ++i) { b[i] = postdata.charCodeAt(i); }
+ xdr.send(b);
+
+ return xdr;
+ }
+
+ // AJAX specific private method
+ obj.pendingAjaxCall = [];
+
+ // Private method
+ obj.gotNextMessages = function (data, status, request, callArgs) {
+ if (urlvars && urlvars['wsmantrace']) { console.log("WSMAN-RECV(" + data.length + "): " + data); }
+ obj.ActiveAjaxCount--;
+ if (obj.FailAllError == 999) return;
+ // console.log("RECV: " + data); // DEBUG
+ if (obj.FailAllError != 0) { callArgs[1](null, obj.FailAllError, callArgs[2]); return; }
+ if (request.status != 200) { callArgs[1](null, request.status, callArgs[2]); obj.PerformNextAjax(); return; }
+ callArgs[1](data, 200, callArgs[2]);
+ obj.PerformNextAjax();
+ }
+
+ // Private method
+ obj.gotNextMessagesError = function (request, status, errorThrown, callArgs) {
+ obj.ActiveAjaxCount--;
+ if (obj.FailAllError == 999) return;
+ if (obj.FailAllError != 0) { callArgs[1](null, obj.FailAllError, callArgs[2]); return; }
+ // if (s != 200) { console.log("ERROR, status=" + status + "\r\n\r\nreq=" + callArgs[0]); } // Debug: Display the request & response if something did not work.
+ if (obj.FailAllError != 999) { callArgs[1]({ Header: { HttpError: request.status } }, request.status, callArgs[2]); }
+ obj.PerformNextAjax();
+ }
+
+ // Cancel all pending queries with given status
+ obj.CancelAllQueries = function (s) {
+ while (obj.PendingAjax.length > 0) { var x = obj.PendingAjax.shift(); x[1](null, s, x[2]); }
+ }
+
+ return obj;
+}
+
diff --git a/amt-wsman-node-0.2.0.js b/amt-wsman-node-0.2.0.js
new file mode 100644
index 0000000..4a633cb
--- /dev/null
+++ b/amt-wsman-node-0.2.0.js
@@ -0,0 +1,392 @@
+/**
+* @description Intel(r) AMT WSMAN communication using Node.js TLS
+* @author Ylian Saint-Hilaire
+* @version v0.2.0b
+*/
+
+// Construct a MeshServer object
+var CreateWsmanComm = function (host, port, user, pass, tls, tlsoptions) {
+ //console.log('CreateWsmanComm', host, port, user, pass, tls, tlsoptions);
+
+ var obj = {};
+ obj.PendingAjax = []; // List of pending AJAX calls. When one frees up, another will start.
+ obj.ActiveAjaxCount = 0; // Number of currently active AJAX calls
+ obj.MaxActiveAjaxCount = 1; // Maximum number of activate AJAX calls at the same time.
+ obj.FailAllError = 0; // Set this to non-zero to fail all AJAX calls with that error status, 999 causes responses to be silent.
+ obj.challengeParams = null;
+ obj.noncecounter = 1;
+ obj.authcounter = 0;
+
+ obj.Address = '/wsman';
+ obj.challengeParams = null;
+ obj.noncecounter = 1;
+ obj.authcounter = 0;
+ obj.cnonce = Math.random().toString(36).substring(7); // Generate a random client nonce
+
+ obj.net = require('net');
+ obj.tls = require('tls');
+ obj.crypto = require('crypto');
+ obj.constants = require('constants');
+ obj.socket = null;
+ obj.socketState = 0;
+ obj.kerberosDone = 0;
+ obj.amtVersion = null;
+
+ obj.host = host;
+ obj.port = port;
+ obj.user = user;
+ obj.pass = pass;
+ obj.xtls = tls;
+ obj.xtlsoptions = tlsoptions;
+ obj.xtlsFingerprint;
+ obj.xtlsCertificate = null;
+ obj.xtlsCheck = 0; // 0 = No TLS, 1 = CA Checked, 2 = Pinned, 3 = Untrusted
+ obj.xtlsSkipHostCheck = 0;
+ obj.xtlsMethod = 0;
+ obj.xtlsDataReceived = false;
+ obj.digestRealmMatch = null;
+ obj.digestRealm = null;
+
+ // Private method
+ //obj.Debug = function (msg) { console.log(msg); }
+
+ // Private method
+ // pri = priority, if set to 1, the call is high priority and put on top of the stack.
+ obj.PerformAjax = function (postdata, callback, tag, pri, url, action) {
+ if ((obj.ActiveAjaxCount == 0 || ((obj.ActiveAjaxCount < obj.MaxActiveAjaxCount) && (obj.challengeParams != null))) && obj.PendingAjax.length == 0) {
+ // There are no pending AJAX calls, perform the call now.
+ obj.PerformAjaxEx(postdata, callback, tag, url, action);
+ } else {
+ // If this is a high priority call, put this call in front of the array, otherwise put it in the back.
+ if (pri == 1) { obj.PendingAjax.unshift([postdata, callback, tag, url, action]); } else { obj.PendingAjax.push([postdata, callback, tag, url, action]); }
+ }
+ }
+
+ // Private method
+ obj.PerformNextAjax = function () {
+ if (obj.ActiveAjaxCount >= obj.MaxActiveAjaxCount || obj.PendingAjax.length == 0) return;
+ var x = obj.PendingAjax.shift();
+ obj.PerformAjaxEx(x[0], x[1], x[2], x[3], x[4]);
+ obj.PerformNextAjax();
+ }
+
+ // Private method
+ obj.PerformAjaxEx = function (postdata, callback, tag, url, action) {
+ if (obj.FailAllError != 0) { obj.gotNextMessagesError({ status: obj.FailAllError }, 'error', null, [postdata, callback, tag, url, action]); return; }
+ if (!postdata) postdata = '';
+ //obj.Debug("SEND: " + postdata); // DEBUG
+
+ obj.ActiveAjaxCount++;
+ return obj.PerformAjaxExNodeJS(postdata, callback, tag, url, action);
+ }
+
+ // NODE.js specific private method
+ obj.pendingAjaxCall = [];
+
+ // NODE.js specific private method
+ obj.PerformAjaxExNodeJS = function (postdata, callback, tag, url, action) { obj.PerformAjaxExNodeJS2(postdata, callback, tag, url, action, 5); }
+
+ // NODE.js specific private method
+ obj.PerformAjaxExNodeJS2 = function (postdata, callback, tag, url, action, retry) {
+ if (retry <= 0 || obj.FailAllError != 0) {
+ // Too many retry, fail here.
+ obj.ActiveAjaxCount--;
+ if (obj.FailAllError != 999) obj.gotNextMessages(null, 'error', { status: ((obj.FailAllError == 0) ? 408 : obj.FailAllError) }, [postdata, callback, tag, url, action]); // 408 is timeout error
+ obj.PerformNextAjax();
+ return;
+ }
+ obj.pendingAjaxCall.push([postdata, callback, tag, url, action, retry]);
+ if (obj.socketState == 0) { obj.xxConnectHttpSocket(); }
+ else if (obj.socketState == 2) { obj.sendRequest(postdata, url, action); }
+ }
+
+ // NODE.js specific private method
+ obj.sendRequest = function (postdata, url, action) {
+ url = url ? url : '/wsman';
+ action = action ? action : 'POST';
+ var h = action + ' ' + url + ' HTTP/1.1\r\n';
+ if (obj.challengeParams != null) {
+ obj.digestRealm = obj.challengeParams['realm'];
+ if (obj.digestRealmMatch && (obj.digestRealm != obj.digestRealmMatch)) {
+ obj.FailAllError = 997; // Cause all new responses to be silent. 997 = Digest Realm check error
+ obj.CancelAllQueries(997);
+ return;
+ }
+ }
+ if ((obj.user == '*') && (kerberos != null)) {
+ // Kerberos Auth
+ if (obj.kerberosDone == 0) {
+ var ticketName = 'HTTP' + ((obj.tls == 1) ? 'S' : '') + '/' + ((obj.pass == '') ? (obj.host + ':' + obj.port) : obj.pass);
+ // Ask for the new Kerberos ticket
+ //console.log('kerberos.getTicket', ticketName);
+ var ticketReturn = kerberos.getTicket(ticketName);
+ if (ticketReturn.returnCode == 0 || ticketReturn.returnCode == 0x90312) {
+ h += 'Authorization: Negotiate ' + ticketReturn.ticket + '\r\n';
+ if (process.platform.indexOf('win') >= 0) {
+ // Clear kerberos tickets on both 32 and 64bit Windows platforms
+ try { require('child_process').exec('%windir%\\system32\\klist purge', function (error, stdout, stderr) { if (error) { require('child_process').exec('%windir%\\sysnative\\klist purge', function (error, stdout, stderr) { if (error) { console.error('Unable to purge kerberos tickets'); } }); } }); } catch (e) { console.log(e); }
+ }
+ } else {
+ console.log('Unexpected Kerberos error code: ' + ticketReturn.returnCode);
+ }
+ obj.kerberosDone = 1;
+ }
+ } else if (obj.challengeParams != null) {
+ var response = hex_md5(hex_md5(obj.user + ':' + obj.challengeParams['realm'] + ':' + obj.pass) + ':' + obj.challengeParams['nonce'] + ':' + obj.noncecounter + ':' + obj.cnonce + ':' + obj.challengeParams['qop'] + ':' + hex_md5(action + ':' + url + ((obj.challengeParams['qop'] == 'auth-int')?(':' + hex_md5(postdata)):'')));
+ h += 'Authorization: ' + obj.renderDigest({ 'username': obj.user, 'realm': obj.challengeParams['realm'], 'nonce': obj.challengeParams['nonce'], 'uri': url, 'qop': obj.challengeParams['qop'], 'response': response, 'nc': obj.noncecounter++, 'cnonce': obj.cnonce }) + '\r\n';
+ }
+ h += 'Host: ' + obj.host + ':' + obj.port + '\r\nContent-Length: ' + postdata.length + '\r\n\r\n' + postdata; // Use Content-Length
+ //h += 'Host: ' + obj.host + ':' + obj.port + '\r\nTransfer-Encoding: chunked\r\n\r\n' + postdata.length.toString(16).toUpperCase() + '\r\n' + postdata + '\r\n0\r\n\r\n'; // Use Chunked-Encoding
+ obj.xxSend(h);
+ //console.log("SEND: " + h); // Display send packet
+ }
+
+ // Parse the HTTP digest header and return a list of key & values.
+ obj.parseDigest = function (header) { return correctedQuoteSplit(header.substring(7)).reduce(function (obj, s) { var parts = s.trim().split('='); obj[parts[0]] = parts[1].replace(new RegExp('\"', 'g'), ''); return obj; }, {}) }
+
+ // Split a string on quotes but do not do it when in quotes
+ function correctedQuoteSplit(str) { return str.split(',').reduce(function (a, c) { if (a.ic) { a.st[a.st.length - 1] += ',' + c } else { a.st.push(c) } if (c.split('"').length % 2 == 0) { a.ic = !a.ic } return a; }, { st: [], ic: false }).st }
+
+ // NODE.js specific private method
+ obj.renderDigest = function (params) {
+ var paramsnames = [];
+ for (i in params) { paramsnames.push(i); }
+ return 'Digest ' + paramsnames.reduce(function (s1, ii) { return s1 + ',' + ii + '="' + params[ii] + '"' }, '').substring(1);
+ }
+
+ // NODE.js specific private method
+ obj.xxConnectHttpSocket = function () {
+ //obj.Debug("xxConnectHttpSocket");
+ obj.socketParseState = 0;
+ obj.socketAccumulator = '';
+ obj.socketHeader = null;
+ obj.socketData = '';
+ obj.socketState = 1;
+ obj.kerberosDone = 0;
+
+ if (obj.xtlsoptions && obj.xtlsoptions.meshServerConnect) {
+ // Use the websocket wrapper to connect to MeshServer server
+ obj.socket = CreateWebSocketWrapper(obj.xtlsoptions.host, obj.xtlsoptions.port, '/webrelay.ashx?user=' + encodeURIComponent(obj.xtlsoptions.username) + '&pass=' + encodeURIComponent(obj.xtlsoptions.password) + '&host=' + encodeURIComponent(obj.host) + '&p=1&tls1only=' + obj.xtlsMethod, obj.xtlsoptions.xtlsFingerprint);
+ obj.socket.setEncoding('binary');
+ obj.socket.setTimeout(6000); // Set socket idle timeout
+ obj.socket.ondata = obj.xxOnSocketData;
+ obj.socket.onclose = function () { if (obj.xtlsDataReceived == false) { obj.xtlsMethod = 1 - obj.xtlsMethod; } obj.xxOnSocketClosed(); }
+ obj.socket.ontimeout = function () { if (obj.xtlsDataReceived == false) { obj.xtlsMethod = 1 - obj.xtlsMethod; } obj.xxOnSocketClosed(); }
+ obj.socket.connect(obj.xxOnSocketConnected);
+ } else if (obj.xtls != 1) {
+ // Connect without TLS
+ obj.socket = new obj.net.Socket();
+ obj.socket.setEncoding('binary');
+ obj.socket.setTimeout(6000); // Set socket idle timeout
+ obj.socket.on('data', obj.xxOnSocketData);
+ obj.socket.on('close', obj.xxOnSocketClosed);
+ obj.socket.on('timeout', obj.xxOnSocketClosed);
+ obj.socket.connect(obj.port, obj.host, obj.xxOnSocketConnected);
+ } else {
+ // Connect with TLS
+ var options = { secureProtocol: ((obj.xtlsMethod == 0) ? 'SSLv23_method' : 'TLSv1_method'), ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: obj.constants.SSL_OP_NO_SSLv2 | obj.constants.SSL_OP_NO_SSLv3 | obj.constants.SSL_OP_NO_COMPRESSION | obj.constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false };
+ if (obj.xtlsoptions) {
+ if (obj.xtlsoptions.ca) options.ca = obj.xtlsoptions.ca;
+ if (obj.xtlsoptions.cert) options.cert = obj.xtlsoptions.cert;
+ if (obj.xtlsoptions.key) options.key = obj.xtlsoptions.key;
+ obj.xtlsoptions = options;
+ }
+ obj.socket = obj.tls.connect(obj.port, obj.host, obj.xtlsoptions, obj.xxOnSocketConnected);
+ obj.socket.setEncoding('binary');
+ obj.socket.setTimeout(6000); // Set socket idle timeout
+ obj.socket.on('data', obj.xxOnSocketData);
+ obj.socket.on('close', obj.xxOnSocketClosed);
+ obj.socket.on('timeout', obj.xxOnSocketClosed);
+ obj.socket.on('error', function (e) { if (e.message && e.message.indexOf('sslv3 alert bad record mac') >= 0) { obj.xtlsMethod = 1 - obj.xtlsMethod; } });
+ }
+ obj.socket.setNoDelay(true); // Disable nagle. We will encode each WSMAN request as a single send block and want to send it at once. This may help Intel AMT handle pipelining?
+ }
+
+ // Get the certificate of Intel AMT
+ obj.getPeerCertificate = function () { if (obj.xtls == 1) { return obj.socket.getPeerCertificate(); } return null; }
+ obj.getPeerCertificateFingerprint = function () { if (obj.xtls == 1) { return obj.socket.getPeerCertificate().fingerprint.split(':').join('').toLowerCase(); } return null; }
+
+ // NODE.js specific private method
+ obj.xxOnSocketConnected = function () {
+ if (obj.socket == null) return;
+ if (obj.xtls == 1) {
+ obj.xtlsCertificate = obj.socket.getPeerCertificate();
+
+ // ###BEGIN###{Certificates}
+ // Setup the forge certificate check
+ var camatch = 0;
+ if (obj.xtlsoptions.ca) {
+ var forgeCert = forge.pki.certificateFromAsn1(forge.asn1.fromDer(atob(obj.xtlsCertificate.raw.toString('base64'))));
+ var caStore = forge.pki.createCaStore(obj.xtlsoptions.ca);
+ // Got thru all certificates in the store and look for a match.
+ for (var i in caStore.certs) {
+ if (camatch == 0) {
+ var c = caStore.certs[i], verified = false;
+ try { verified = c.verify(forgeCert); } catch (e) { }
+ if (verified == true) { camatch = c; }
+ }
+ }
+ // We found a match, check that the CommonName matches the hostname
+ if ((obj.xtlsSkipHostCheck == 0) && (camatch != 0)) {
+ amtcertname = forgeCert.subject.getField('CN').value;
+ if (amtcertname.toLowerCase() != obj.host.toLowerCase()) { camatch = 0; }
+ }
+ }
+ if ((camatch == 0) && (obj.xtlsFingerprint != 0) && (obj.xtlsCertificate.fingerprint.split(':').join('').toLowerCase() != obj.xtlsFingerprint)) {
+ obj.FailAllError = 998; // Cause all new responses to be silent. 998 = TLS Certificate check error
+ obj.CancelAllQueries(998);
+ return;
+ }
+ if ((obj.xtlsFingerprint == 0) && (camatch == 0)) { obj.xtlsCheck = 3; } else { obj.xtlsCheck = (camatch == 0) ? 2 : 1; }
+ // ###END###{Certificates}
+ // ###BEGIN###{!Certificates}
+ if ((obj.xtlsFingerprint != 0) && (obj.xtlsCertificate.fingerprint.split(':').join('').toLowerCase() != obj.xtlsFingerprint)) {
+ obj.FailAllError = 998; // Cause all new responses to be silent. 998 = TLS Certificate check error
+ obj.CancelAllQueries(998);
+ return;
+ }
+ obj.xtlsCheck = 2;
+ // ###END###{!Certificates}
+ } else { obj.xtlsCheck = 0; }
+ obj.socketState = 2;
+ obj.socketParseState = 0;
+ for (i in obj.pendingAjaxCall) { obj.sendRequest(obj.pendingAjaxCall[i][0], obj.pendingAjaxCall[i][3], obj.pendingAjaxCall[i][4]); }
+ }
+
+ // NODE.js specific private method
+ obj.xxOnSocketData = function (data) {
+ obj.xtlsDataReceived = true;
+ if (urlvars && urlvars['wsmantrace']) { console.log("WSMAN-RECV(" + data.length + "): " + data); }
+ if (typeof data === 'object') {
+ // This is an ArrayBuffer, convert it to a string array (used in IE)
+ var binary = "", bytes = new Uint8Array(data), length = bytes.byteLength;
+ for (var i = 0; i < length; i++) { binary += String.fromCharCode(bytes[i]); }
+ data = binary;
+ }
+ else if (typeof data !== 'string') return;
+
+ obj.socketAccumulator += data;
+ while (true) {
+ //console.log('ACC(' + obj.socketAccumulator + '): ' + obj.socketAccumulator);
+ if (obj.socketParseState == 0) {
+ var headersize = obj.socketAccumulator.indexOf('\r\n\r\n');
+ if (headersize < 0) return;
+ //obj.Debug(obj.socketAccumulator.substring(0, headersize)); // Display received HTTP header
+ obj.socketHeader = obj.socketAccumulator.substring(0, headersize).split('\r\n');
+ if (obj.amtVersion == null) { for (var i in obj.socketHeader) { if (obj.socketHeader[i].indexOf('Server: Intel(R) Active Management Technology ') == 0) { obj.amtVersion = obj.socketHeader[i].substring(46); } } }
+ obj.socketAccumulator = obj.socketAccumulator.substring(headersize + 4);
+ obj.socketParseState = 1;
+ obj.socketData = '';
+ obj.socketXHeader = { Directive: obj.socketHeader[0].split(' ') };
+ for (i in obj.socketHeader) {
+ if (i != 0) {
+ var x2 = obj.socketHeader[i].indexOf(':');
+ obj.socketXHeader[obj.socketHeader[i].substring(0, x2).toLowerCase()] = obj.socketHeader[i].substring(x2 + 2);
+ }
+ }
+ }
+ if (obj.socketParseState == 1) {
+ var csize = -1;
+ if ((obj.socketXHeader["connection"] != undefined) && (obj.socketXHeader["connection"].toLowerCase() == 'close') && ((obj.socketXHeader["transfer-encoding"] == undefined) || (obj.socketXHeader["transfer-encoding"].toLowerCase() != 'chunked'))) {
+ // The body ends with a close, in this case, we will only process the header
+ csize = 0;
+ } else if (obj.socketXHeader["content-length"] != undefined) {
+ // The body length is specified by the content-length
+ csize = parseInt(obj.socketXHeader["content-length"]);
+ if (obj.socketAccumulator.length < csize) return;
+ var data = obj.socketAccumulator.substring(0, csize);
+ obj.socketAccumulator = obj.socketAccumulator.substring(csize);
+ obj.socketData = data;
+ csize = 0;
+ } else {
+ // The body is chunked
+ var clen = obj.socketAccumulator.indexOf("\r\n");
+ if (clen < 0) return; // Chunk length not found, exit now and get more data.
+ // Chunk length if found, lets see if we can get the data.
+ csize = parseInt(obj.socketAccumulator.substring(0, clen), 16);
+ if (obj.socketAccumulator.length < clen + 2 + csize + 2) return;
+ // We got a chunk with all of the data, handle the chunck now.
+ var data = obj.socketAccumulator.substring(clen + 2, clen + 2 + csize);
+ obj.socketAccumulator = obj.socketAccumulator.substring(clen + 2 + csize + 2);
+ obj.socketData += data;
+ }
+ if (csize == 0) {
+ //obj.Debug("xxOnSocketData DONE: (" + obj.socketData.length + "): " + obj.socketData);
+ obj.xxProcessHttpResponse(obj.socketXHeader, obj.socketData);
+ obj.socketParseState = 0;
+ obj.socketHeader = null;
+ }
+ }
+ }
+ }
+
+ // NODE.js specific private method
+ obj.xxProcessHttpResponse = function (header, data) {
+ //obj.Debug("xxProcessHttpResponse: " + header.Directive[1]);
+
+ var s = parseInt(header.Directive[1]);
+ if (isNaN(s)) s = 500;
+ if (s == 401 && ++(obj.authcounter) < 3) {
+ obj.challengeParams = obj.parseDigest(header['www-authenticate']); // Set the digest parameters, after this, the socket will close and we will auto-retry
+ if (obj.challengeParams['qop'] != null) {
+ var qopList = obj.challengeParams['qop'].split(',');
+ for (var i in qopList) { qopList[i] = qopList[i].trim(); }
+ if (qopList.indexOf('auth-int') >= 0) { obj.challengeParams['qop'] = 'auth-int'; } else { obj.challengeParams['qop'] = 'auth'; }
+ }
+ obj.socket.end();
+ } else {
+ var r = obj.pendingAjaxCall.shift();
+ if (r == null || r.length < 1) { console.log("pendingAjaxCall error, " + r); return; }
+ //if (s != 200) { obj.Debug("Error, status=" + s + "\r\n\r\nreq=" + r[0] + "\r\n\r\nresp=" + data); } // Debug: Display the request & response if something did not work.
+ obj.authcounter = 0;
+ obj.ActiveAjaxCount--;
+ obj.gotNextMessages(data, 'success', { status: s }, r);
+ obj.PerformNextAjax();
+ }
+ }
+
+ // NODE.js specific private method
+ obj.xxOnSocketClosed = function (data) {
+ //obj.Debug("xxOnSocketClosed");
+ obj.socketState = 0;
+ if (obj.socket != null) { obj.socket.destroy(); obj.socket = null; }
+ if (obj.pendingAjaxCall.length > 0) {
+ var r = obj.pendingAjaxCall.shift();
+ var retry = r[5];
+ setTimeout(function () { obj.PerformAjaxExNodeJS2(r[0], r[1], r[2], r[3], r[4], --retry) }, 500); // Wait half a second and try again
+ }
+ }
+
+ // NODE.js specific private method
+ obj.xxSend = function (x) {
+ if (obj.socketState == 2) {
+ if (urlvars && urlvars['wsmantrace']) { console.log("WSMAN-SEND(" + x.length + "): " + x); }
+ obj.socket.write(new Buffer(x, 'binary'));
+ }
+ }
+
+ // Cancel all pending queries with given status
+ obj.CancelAllQueries = function (s) {
+ obj.FailAllError = s;
+ while (obj.PendingAjax.length > 0) { var x = obj.PendingAjax.shift(); x[1](null, s, x[2]); }
+ if (obj.socket != null) { obj.socket.end(); obj.socket = null; obj.socketState = 0; }
+ }
+
+ // Private method
+ obj.gotNextMessages = function (data, status, request, callArgs) {
+ if (obj.FailAllError == 999) return;
+ if (obj.FailAllError != 0) { try { callArgs[1](null, obj.FailAllError, callArgs[2]); } catch (ex) { console.error(ex); } return; }
+ if (request.status != 200) { try { callArgs[1](null, request.status, callArgs[2]); } catch (ex) { console.error(ex); } return; }
+ try { callArgs[1](data, 200, callArgs[2]); } catch (ex) { console.error(ex); }
+ }
+
+ // Private method
+ obj.gotNextMessagesError = function (request, status, errorThrown, callArgs) {
+ if (obj.FailAllError == 999) return;
+ if (obj.FailAllError != 0) { try { callArgs[1](null, obj.FailAllError, callArgs[2]); } catch (ex) { console.error(ex); } return; }
+ try { callArgs[1](obj, null, { Header: { HttpError: request.status } }, request.status, callArgs[2]); } catch (ex) { console.error(ex); }
+ }
+
+ return obj;
+}
+
diff --git a/amt-wsman-ws-0.2.0.js b/amt-wsman-ws-0.2.0.js
new file mode 100644
index 0000000..da69d05
--- /dev/null
+++ b/amt-wsman-ws-0.2.0.js
@@ -0,0 +1,315 @@
+/**
+* @description WSMAN communication using websocket
+* @author Ylian Saint-Hilaire
+* @version v0.2.0c
+*/
+
+// Construct a WSMAN communication object
+var CreateWsmanComm = function (host, port, user, pass, tls) {
+ var obj = {};
+ obj.PendingAjax = []; // List of pending AJAX calls. When one frees up, another will start.
+ obj.ActiveAjaxCount = 0; // Number of currently active AJAX calls
+ obj.MaxActiveAjaxCount = 1; // Maximum number of activate AJAX calls at the same time.
+ obj.FailAllError = 0; // Set this to non-zero to fail all AJAX calls with that error status, 999 causes responses to be silent.
+ obj.challengeParams = null;
+ obj.noncecounter = 1;
+ obj.authcounter = 0;
+ obj.socket = null;
+ obj.socketState = 0;
+ obj.host = host;
+ obj.port = port;
+ obj.user = user;
+ obj.pass = pass;
+ obj.tls = tls;
+ obj.tlsv1only = 0;
+ obj.cnonce = Math.random().toString(36).substring(7); // Generate a random client nonce
+ obj.inDataCount = 0;
+ obj.amtVersion = null;
+ obj.digestRealmMatch = null;
+ obj.digestRealm = null;
+
+ // Private method
+ //obj.Debug = function (msg) { console.log(msg); }
+
+ // Private method
+ // pri = priority, if set to 1, the call is high priority and put on top of the stack.
+ obj.PerformAjax = function (postdata, callback, tag, pri, url, action) {
+ if (obj.ActiveAjaxCount < obj.MaxActiveAjaxCount && obj.PendingAjax.length == 0) {
+ // There are no pending AJAX calls, perform the call now.
+ obj.PerformAjaxEx(postdata, callback, tag, url, action);
+ } else {
+ // If this is a high priority call, put this call in front of the array, otherwise put it in the back.
+ if (pri == 1) { obj.PendingAjax.unshift([postdata, callback, tag, url, action]); } else { obj.PendingAjax.push([postdata, callback, tag, url, action]); }
+ }
+ }
+
+ // Private method
+ obj.PerformNextAjax = function () {
+ if (obj.ActiveAjaxCount >= obj.MaxActiveAjaxCount || obj.PendingAjax.length == 0) return;
+ var x = obj.PendingAjax.shift();
+ obj.PerformAjaxEx(x[0], x[1], x[2], x[3], x[4]);
+ obj.PerformNextAjax();
+ }
+
+ // Private method
+ obj.PerformAjaxEx = function (postdata, callback, tag, url, action) {
+ if (obj.FailAllError != 0) { obj.gotNextMessagesError({ status: obj.FailAllError }, 'error', null, [postdata, callback, tag, url, action]); return; }
+ if (!postdata) postdata = "";
+ //console.log("SEND: " + postdata); // DEBUG
+
+ // We are in a websocket relay environment
+ obj.ActiveAjaxCount++;
+ return obj.PerformAjaxExNodeJS(postdata, callback, tag, url, action);
+ }
+
+ // Websocket relay specific private method
+ obj.pendingAjaxCall = [];
+
+ // Websocket relay specific private method
+ obj.PerformAjaxExNodeJS = function (postdata, callback, tag, url, action) { obj.PerformAjaxExNodeJS2(postdata, callback, tag, url, action, 5); }
+
+ // Websocket relay specific private method
+ obj.PerformAjaxExNodeJS2 = function (postdata, callback, tag, url, action, retry) {
+ //console.log('PerformAjaxExNodeJS2', postdata, retry);
+ if (retry <= 0 || obj.FailAllError != 0) {
+ // Too many retry, fail here.
+ obj.ActiveAjaxCount--;
+ if (obj.FailAllError != 999) obj.gotNextMessages(null, 'error', { status: ((obj.FailAllError == 0) ? 408 : obj.FailAllError) }, [postdata, callback, tag, url, action]); // 408 is timeout error
+ obj.PerformNextAjax();
+ return;
+ }
+ obj.pendingAjaxCall.push([postdata, callback, tag, url, action, retry]);
+ if (obj.socketState == 0) { obj.xxConnectHttpSocket(); }
+ else if (obj.socketState == 2) { obj.sendRequest(postdata, url, action); }
+ }
+
+ // Websocket relay specific private method (Content Length Encoding)
+ obj.sendRequest = function (postdata, url, action) {
+ url = url ? url : "/wsman";
+ action = action ? action : "POST";
+ var h = action + " " + url + " HTTP/1.1\r\n";
+ if (obj.challengeParams != null) {
+ obj.digestRealm = obj.challengeParams["realm"];
+ if (obj.digestRealmMatch && (obj.digestRealm != obj.digestRealmMatch)) {
+ obj.FailAllError = 997; // Cause all new responses to be silent. 997 = Digest Realm check error
+ obj.CancelAllQueries(997);
+ return;
+ }
+ var response = hex_md5(hex_md5(obj.user + ':' + obj.challengeParams['realm'] + ':' + obj.pass) + ':' + obj.challengeParams['nonce'] + ':' + obj.noncecounter + ':' + obj.cnonce + ':' + obj.challengeParams['qop'] + ':' + hex_md5(action + ':' + url + ((obj.challengeParams['qop'] == 'auth-int') ? (':' + hex_md5(postdata)) : '')));
+ h += 'Authorization: ' + obj.renderDigest({ 'username': obj.user, 'realm': obj.challengeParams['realm'], 'nonce': obj.challengeParams['nonce'], 'uri': url, 'qop': obj.challengeParams['qop'], 'response': response, 'nc': obj.noncecounter++, 'cnonce': obj.cnonce }) + '\r\n';
+ }
+ h += 'Host: ' + obj.host + ':' + obj.port + '\r\nContent-Length: ' + postdata.length + '\r\n\r\n' + postdata; // Use Content-Length
+ //h += 'Host: ' + obj.host + ':' + obj.port + '\r\nTransfer-Encoding: chunked\r\n\r\n' + postdata.length.toString(16).toUpperCase() + '\r\n' + postdata + '\r\n0\r\n\r\n'; // Use Chunked-Encoding
+ _Send(h);
+ }
+
+ // Parse the HTTP digest header and return a list of key & values.
+ obj.parseDigest = function (header) { return correctedQuoteSplit(header.substring(7)).reduce(function (obj, s) { var parts = s.trim().split('='); obj[parts[0]] = parts[1].replace(new RegExp('\"', 'g'), ''); return obj; }, {}) }
+
+ // Split a string on quotes but do not do it when in quotes
+ function correctedQuoteSplit(str) { return str.split(',').reduce(function (a, c) { if (a.ic) { a.st[a.st.length - 1] += ',' + c } else { a.st.push(c) } if (c.split('"').length % 2 == 0) { a.ic = !a.ic } return a; }, { st: [], ic: false }).st }
+
+ // Websocket relay specific private method
+ obj.renderDigest = function (params) {
+ var paramsnames = [];
+ for (i in params) { paramsnames.push(i); }
+ return 'Digest ' + paramsnames.reduce(function (s1, ii) { return s1 + ',' + ii + '="' + params[ii] + '"' }, '').substring(1);
+ }
+
+ // Websocket relay specific private method
+ obj.xxConnectHttpSocket = function () {
+ //obj.Debug("xxConnectHttpSocket");
+ obj.inDataCount = 0;
+ obj.socketState = 1;
+ obj.socket = new WebSocket(window.location.protocol.replace("http", "ws") + "//" + window.location.host + window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) + "/webrelay.ashx?p=1&host=" + obj.host + "&port=" + obj.port + "&tls=" + obj.tls + "&tls1only=" + obj.tlsv1only + ((user == '*') ? "&serverauth=1" : "") + ((typeof pass === "undefined") ? ("&serverauth=1&user=" + user) : "")); // The "p=1" indicates to the relay that this is a WSMAN session
+ obj.socket.onopen = _OnSocketConnected;
+ obj.socket.onmessage = _OnMessage;
+ obj.socket.onclose = _OnSocketClosed;
+ }
+
+ // Websocket relay specific private method
+ function _OnSocketConnected() {
+ obj.socketState = 2;
+ obj.socketParseState = 0;
+ obj.socketAccumulator = '';
+ obj.socketHeader = null;
+ obj.socketData = '';
+ //console.log("xxOnSocketConnected");
+ for (i in obj.pendingAjaxCall) { obj.sendRequest(obj.pendingAjaxCall[i][0], obj.pendingAjaxCall[i][3], obj.pendingAjaxCall[i][4]); }
+ }
+
+ // Setup the file reader
+ var fileReader = new FileReader();
+ var fileReaderInuse = false, fileReaderAcc = [];
+ if (fileReader.readAsBinaryString) {
+ // Chrome & Firefox (Draft)
+ fileReader.onload = function (e) { _OnSocketData(e.target.result); if (fileReaderAcc.length == 0) { fileReaderInuse = false; } else { fileReader.readAsBinaryString(new Blob([fileReaderAcc.shift()])); } }
+ } else if (fileReader.readAsArrayBuffer) {
+ // Chrome & Firefox (Spec)
+ fileReader.onloadend = function (e) { _OnSocketData(e.target.result); if (fileReaderAcc.length == 0) { fileReaderInuse = false; } else { fileReader.readAsArrayBuffer(fileReaderAcc.shift()); } }
+ }
+
+ function _OnMessage(e) {
+ if (typeof e.data == 'object') {
+ if (fileReaderInuse == true) { fileReaderAcc.push(e.data); return; }
+ if (fileReader.readAsBinaryString) {
+ // Chrome & Firefox (Draft)
+ fileReaderInuse = true;
+ fileReader.readAsBinaryString(new Blob([e.data]));
+ } else if (fileReader.readAsArrayBuffer) {
+ // Chrome & Firefox (Spec)
+ fileReaderInuse = true;
+ fileReader.readAsArrayBuffer(e.data);
+ } else {
+ // IE10, readAsBinaryString does not exist, use an alternative.
+ var binary = "", bytes = new Uint8Array(e.data), length = bytes.byteLength;
+ for (var i = 0; i < length; i++) { binary += String.fromCharCode(bytes[i]); }
+ _OnSocketData(binary);
+ }
+ } else {
+ _OnSocketData(e.data);
+ }
+ };
+
+ // Websocket relay specific private method
+ function _OnSocketData(data) {
+ //obj.Debug("_OnSocketData (" + data.length + "): " + data);
+
+ if (typeof data === 'object') {
+ // This is an ArrayBuffer, convert it to a string array (used in IE)
+ var binary = "", bytes = new Uint8Array(data), length = bytes.byteLength;
+ for (var i = 0; i < length; i++) { binary += String.fromCharCode(bytes[i]); }
+ data = binary;
+ }
+ else if (typeof data !== 'string') return;
+
+ //console.log("RECV(" + obj.socketParseState + "): " + data); // DEBUG
+
+ obj.socketAccumulator += data;
+ while (true) {
+ if (obj.socketParseState == 0) {
+ var headersize = obj.socketAccumulator.indexOf("\r\n\r\n");
+ if (headersize < 0) return;
+ //obj.Debug(obj.socketAccumulator.substring(0, headersize)); // Display received HTTP header
+ obj.socketHeader = obj.socketAccumulator.substring(0, headersize).split("\r\n");
+ if (obj.amtVersion == null) { for (var i in obj.socketHeader) { if (obj.socketHeader[i].indexOf('Server: Intel(R) Active Management Technology ') == 0) { obj.amtVersion = obj.socketHeader[i].substring(46); } } }
+ obj.socketAccumulator = obj.socketAccumulator.substring(headersize + 4);
+ obj.socketParseState = 1;
+ obj.socketData = '';
+ obj.socketXHeader = { Directive: obj.socketHeader[0].split(' ') };
+ //console.log("Header", obj.socketXHeader);
+ for (i in obj.socketHeader) {
+ if (i != 0) {
+ var x2 = obj.socketHeader[i].indexOf(':');
+ obj.socketXHeader[obj.socketHeader[i].substring(0, x2).toLowerCase()] = obj.socketHeader[i].substring(x2 + 2);
+ }
+ }
+ }
+ if (obj.socketParseState == 1) {
+ var csize = -1;
+ if ((obj.socketXHeader['connection'] != undefined) && (obj.socketXHeader['connection'].toLowerCase() == 'close') && ((obj.socketXHeader["transfer-encoding"] == undefined) || (obj.socketXHeader["transfer-encoding"].toLowerCase() != 'chunked'))) {
+ // The body ends with a close, in this case, we will only process the header
+ csize = 0;
+ } else if (obj.socketXHeader['content-length'] != undefined) {
+ // The body length is specified by the content-length
+ csize = parseInt(obj.socketXHeader['content-length']);
+ if (obj.socketAccumulator.length < csize) return;
+ var data = obj.socketAccumulator.substring(0, csize);
+ obj.socketAccumulator = obj.socketAccumulator.substring(csize);
+ obj.socketData = data;
+ csize = 0;
+ } else {
+ // The body is chunked
+ var clen = obj.socketAccumulator.indexOf('\r\n');
+ if (clen < 0) return; // Chunk length not found, exit now and get more data.
+ // Chunk length if found, lets see if we can get the data.
+ csize = parseInt(obj.socketAccumulator.substring(0, clen), 16);
+ if (isNaN(csize)) { if (obj.websocket) { obj.websocket.close(); } return; } // Critical error, close the socket and exit.
+ if (obj.socketAccumulator.length < clen + 2 + csize + 2) return;
+ // We got a chunk with all of the data, handle the chunck now.
+ var data = obj.socketAccumulator.substring(clen + 2, clen + 2 + csize);
+ obj.socketAccumulator = obj.socketAccumulator.substring(clen + 2 + csize + 2);
+ obj.socketData += data;
+ }
+ if (csize == 0) {
+ //obj.Debug("_OnSocketData DONE: (" + obj.socketData.length + "): " + obj.socketData);
+ _ProcessHttpResponse(obj.socketXHeader, obj.socketData);
+ obj.socketParseState = 0;
+ obj.socketHeader = null;
+ }
+ }
+ }
+ }
+
+ // Websocket relay specific private method
+ function _ProcessHttpResponse(header, data) {
+ //obj.Debug("_ProcessHttpResponse: " + header.Directive[1]);
+
+ var s = parseInt(header.Directive[1]);
+ if (isNaN(s)) {
+ s = 602;
+ }
+ if (s == 401 && ++(obj.authcounter) < 3) {
+ obj.challengeParams = obj.parseDigest(header['www-authenticate']); // Set the digest parameters, after this, the socket will close and we will auto-retry
+ if (obj.challengeParams['qop'] != null) {
+ var qopList = obj.challengeParams['qop'].split(',');
+ for (var i in qopList) { qopList[i] = qopList[i].trim(); }
+ if (qopList.indexOf('auth-int') >= 0) { obj.challengeParams['qop'] = 'auth-int'; } else { obj.challengeParams['qop'] = 'auth'; }
+ }
+ } else {
+ var r = obj.pendingAjaxCall.shift();
+ // if (s != 200) { obj.Debug("Error, status=" + s + "\r\n\r\nreq=" + r[0] + "\r\n\r\nresp=" + data); } // Debug: Display the request & response if something did not work.
+ obj.authcounter = 0;
+ obj.ActiveAjaxCount--;
+ obj.gotNextMessages(data, 'success', { status: s }, r);
+ obj.PerformNextAjax();
+ }
+ }
+
+ // Websocket relay specific private method
+ function _OnSocketClosed(data) {
+ //console.log("_OnSocketClosed");
+ if (obj.inDataCount == 0) { obj.tlsv1only = (1 - obj.tlsv1only); }
+ obj.socketState = 0;
+ if (obj.socket != null) { obj.socket.close(); obj.socket = null; }
+ if (obj.pendingAjaxCall.length > 0) {
+ var r = obj.pendingAjaxCall.shift();
+ var retry = r[5];
+ obj.PerformAjaxExNodeJS2(r[0], r[1], r[2], r[3], r[4], --retry);
+ }
+ }
+
+ // Websocket relay specific private method
+ function _Send(x) {
+ //console.log("SEND: " + x); // DEBUG
+ if (obj.socketState == 2 && obj.socket != null && obj.socket.readyState == WebSocket.OPEN) {
+ var b = new Uint8Array(x.length);
+ for (var i = 0; i < x.length; ++i) { b[i] = x.charCodeAt(i); }
+ try { obj.socket.send(b.buffer); } catch (e) { }
+ }
+ }
+
+ // Private method
+ obj.gotNextMessages = function (data, status, request, callArgs) {
+ if (obj.FailAllError == 999) return;
+ if (obj.FailAllError != 0) { callArgs[1](null, obj.FailAllError, callArgs[2]); return; }
+ if (request.status != 200) { callArgs[1](null, request.status, callArgs[2]); return; }
+ callArgs[1](data, 200, callArgs[2]);
+ }
+
+ // Private method
+ obj.gotNextMessagesError = function (request, status, errorThrown, callArgs) {
+ if (obj.FailAllError == 999) return;
+ if (obj.FailAllError != 0) { callArgs[1](null, obj.FailAllError, callArgs[2]); return; }
+ callArgs[1](obj, null, { Header: { HttpError: request.status } }, request.status, callArgs[2]);
+ }
+
+ // Cancel all pending queries with given status
+ obj.CancelAllQueries = function (s) {
+ while (obj.PendingAjax.length > 0) { var x = obj.PendingAjax.shift(); x[1](null, s, x[2]); }
+ if (obj.websocket != null) { obj.websocket.close(); obj.websocket = null; obj.socketState = 0; }
+ }
+
+ return obj;
+}
+
diff --git a/certificate.png b/certificate.png
new file mode 100644
index 0000000..3de9ee5
Binary files /dev/null and b/certificate.png differ
diff --git a/closure-externs/crypto.js b/closure-externs/crypto.js
new file mode 100644
index 0000000..64ff6b0
--- /dev/null
+++ b/closure-externs/crypto.js
@@ -0,0 +1,578 @@
+/*
+ * Copyright 2012 The Closure Compiler Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for node's crypto module. Depends on the buffer module.
+ * @see http://nodejs.org/api/crypto.html
+ * @see https://github.com/joyent/node/blob/master/lib/crypto.js
+ * @externs
+ * @author Daniel Wirtz
+ */
+
+/**
+ BEGIN_NODE_INCLUDE
+ var crypto = require('crypto');
+ END_NODE_INCLUDE
+ */
+
+/**
+ * @type {Object.}
+ */
+var crypto = {};
+
+/**
+ * @type {string}
+ */
+crypto.DEFAULT_ENCODING;
+
+/**
+ * @typedef {{pfx: (string|buffer.Buffer), key: (string|buffer.Buffer), passphrase: string, cert: (string|buffer.Buffer), ca: Array., crl: (string|Array.), ciphers: string}}
+ */
+crypto.Credentials;
+
+/**
+ * @param {Object.=} details
+ * @return {crypto.Credentials}
+ */
+crypto.createCredentials =
+function(details) {};
+
+/**
+ * @param {string} algorithm
+ * @return {crypto.Hash}
+ */
+crypto.createHash =
+function(algorithm) {};
+
+/**
+ * @param {string} algorithm
+ * @param {Object=} options
+ * @constructor
+ * @extends stream.Transform
+ */
+crypto.Hash =
+function(algorithm, options) {};
+
+/**
+ * @param {string|buffer.Buffer} data
+ * @param {string=} input_encoding
+ */
+crypto.Hash.prototype.update =
+function(data, input_encoding) {};
+
+/**
+ * @param {string=} encoding
+ * @return {string}
+ */
+crypto.Hash.prototype.digest =
+function(encoding) {};
+
+/**
+ * @param {string} algorithm
+ * @param {string|buffer.Buffer} key
+ * @return {crypto.Hmac}
+ */
+crypto.createHmac =
+function(algorithm, key) {};
+
+/**
+ * @param {string} hmac
+ * @param {string|buffer.Buffer} key
+ * @param {Object=} options
+ * @constructor
+ * @extends stream.Transform
+ */
+crypto.Hmac =
+function(hmac, key, options) {};
+
+/**
+ * @param {string|buffer.Buffer} data
+ */
+crypto.Hmac.prototype.update =
+function(data) {};
+
+/**
+ * @param {string} encoding
+ */
+crypto.Hmac.prototype.digest =
+function(encoding) {};
+
+/**
+ * @param {string} algorithm
+ * @param {string|buffer.Buffer} password
+ * @return {crypto.Cipher}
+ */
+crypto.createCipher =
+function(algorithm, password) {};
+
+/**
+ * @param {string} algorithm
+ * @param {string|buffer.Buffer} key
+ * @param {string|buffer.Buffer} iv
+ * @return {crypto.Cipheriv}
+ */
+crypto.createCipheriv =
+function(algorithm, key, iv) {};
+
+/**
+ * @param {string|buffer.Buffer} cipher
+ * @param {string} password
+ * @param {Object=} options
+ * @constructor
+ * @extends stream.Transform
+ */
+crypto.Cipher =
+function(cipher, password, options) {};
+
+/**
+ * @param {string|buffer.Buffer} data
+ * @param {string=} input_encoding
+ * @param {string=} output_encoding
+ * @return {string|buffer.Buffer}
+ */
+crypto.Cipher.prototype.update =
+function(data, input_encoding, output_encoding) {};
+
+/**
+ * @name crypto.Cipher.prototype.final
+ * @param {string} output_encoding
+ * @return {string|buffer.Buffer}
+ */
+crypto.Cipher.prototype['final'] =
+function(output_encoding) {};
+
+/**
+ * @param {boolean=} auto_padding
+ */
+crypto.Cipher.prototype.setAutoPadding =
+function(auto_padding) {};
+
+/**
+ * Note: Cipheriv mixes update, final, and setAutoPadding from Cipher but
+ * doesn't inherit directly from Cipher.
+ *
+ * @param {string} cipher
+ * @param {string|buffer.Buffer} key
+ * @param {string|buffer.Buffer} iv
+ * @constructor
+ * @extends stream.Transform
+ */
+crypto.Cipheriv =
+function(cipher, key, iv) {};
+
+/**
+ * @param {string|buffer.Buffer} data
+ * @param {string=} input_encoding
+ * @param {string=} output_encoding
+ * @return {string|buffer.Buffer}
+ */
+crypto.Cipheriv.prototype.update =
+function(data, input_encoding, output_encoding) {};
+
+/**
+ * @name crypto.Cipheriv.prototype.final
+ * @param {string} output_encoding
+ * @return {string|buffer.Buffer}
+ */
+crypto.Cipheriv.prototype['final'] =
+function(output_encoding) {};
+
+/**
+ * @param {boolean=} auto_padding
+ */
+crypto.Cipheriv.prototype.setAutoPadding =
+function(auto_padding) {};
+
+/**
+ * @param {string} algorithm
+ * @param {string|buffer.Buffer} password
+ * @return {crypto.Decipher}
+ */
+crypto.createDecipher =
+function(algorithm, password) {};
+
+/**
+ * @param {string} algorithm
+ * @param {string|buffer.Buffer} key
+ * @param {string|buffer.Buffer} iv
+ * @return {crypto.Decipheriv}
+ */
+crypto.createDecipheriv =
+function(algorithm, key, iv) {};
+
+/**
+ * Note: Decipher mixes update, final, and setAutoPadding from Cipher but
+ * doesn't inherit directly from Cipher.
+ *
+ * @param {string|buffer.Buffer} cipher
+ * @param {string|buffer.Buffer} password
+ * @param {Object=} options
+ * @constructor
+ * @extends stream.Transform
+ */
+crypto.Decipher =
+function(cipher, password, options) {}
+
+/**
+ * @param {string|buffer.Buffer} data
+ * @param {string=} input_encoding
+ * @param {string=} output_encoding
+ * @return {string|buffer.Buffer}
+ */
+crypto.Decipher.prototype.update =
+function(data, input_encoding, output_encoding) {};
+
+/**
+ * @name crypto.Decipher.prototype.final
+ * @param {string} output_encoding
+ * @return {string|buffer.Buffer}
+ */
+crypto.Decipher.prototype['final'] =
+function(output_encoding) {};
+
+/**
+ * @param {string} output_encoding
+ * @return {string|buffer.Buffer}
+ */
+crypto.Decipher.prototype.finaltol =
+function(output_encoding) {};
+
+/**
+ * @param {boolean=} auto_padding
+ */
+crypto.Decipher.prototype.setAutoPadding =
+function(auto_padding) {};
+
+/**
+ * Note: Decipheriv mixes update, final, and setAutoPadding from Cipher but
+ * doesn't inherit directly from Cipher.
+ *
+ * @param {string|buffer.Buffer|crypto.Decipheriv} cipher
+ * @param {string|buffer.Buffer} key
+ * @param {string|buffer.Buffer} iv
+ * @param {Object=} options
+ * @constructor
+ * @extends stream.Transform
+ */
+crypto.Decipheriv =
+function(cipher, key, iv, options) {};
+
+/**
+ * @param {string|buffer.Buffer} data
+ * @param {string=} input_encoding
+ * @param {string=} output_encoding
+ * @return {string|buffer.Buffer}
+ */
+crypto.Decipheriv.prototype.update =
+function(data, input_encoding, output_encoding) {};
+
+/**
+ * @name crypto.Decipheriv.prototype.final
+ * @param {string} output_encoding
+ * @return {string|buffer.Buffer}
+ */
+crypto.Decipheriv.prototype['final'] =
+function(output_encoding) {};
+
+/**
+ * @param {string} output_encoding
+ * @return {string|buffer.Buffer}
+ */
+crypto.Decipheriv.prototype.finaltol =
+function(output_encoding) {};
+
+/**
+ * @param {boolean=} auto_padding
+ */
+crypto.Decipheriv.prototype.setAutoPadding =
+function(auto_padding) {};
+
+/**
+ * @param {string} algorithm
+ * @return {crypto.Sign}
+ */
+crypto.createSign =
+function(algorithm) {};
+
+/**
+ * @param {string} algorithm
+ * @param {Object=} options
+ * @constructor
+ * @extends stream.Writable
+ */
+crypto.Sign =
+function(algorithm, options) {};
+
+/**
+ * @param {string|buffer.Buffer} data
+ */
+crypto.Sign.prototype.update =
+function(data) {};
+
+/**
+ * @param {string} private_key
+ * @param {string=} output_format
+ * @return {string|buffer.Buffer}
+ */
+crypto.Sign.prototype.sign =
+function(private_key, output_format) {};
+
+/**
+ * @param {string} algorithm
+ * @return crypto.Verify
+ */
+crypto.createVerify =
+function(algorithm) {};
+
+/**
+ * @param {string} algorithm
+ * @param {Object=} options
+ * @constructor
+ * @extends stream.Writable
+ */
+crypto.Verify =
+function(algorithm, options) {};
+
+/**
+ * @param {string|buffer.Buffer} data
+ */
+crypto.Verify.prototype.update =
+function(data) {};
+
+/**
+ * @param {string} object
+ * @param {string|buffer.Buffer} signature
+ * @param {string=} signature_format
+ * @return {boolean}
+ */
+crypto.Verify.prototype.verify =
+function(object, signature, signature_format) {};
+
+/**
+ * @param {number} prime
+ * @param {string=} encoding
+ * @return {crypto.DiffieHellman}
+ */
+crypto.createDiffieHellman =
+function(prime, encoding) {};
+
+/**
+ * @param {number} sizeOrKey
+ * @param {string=} encoding
+ * @constructor
+ */
+crypto.DiffieHellman =
+function(sizeOrKey, encoding) {};
+
+/**
+ * @param {string=} encoding
+ * @return {string|buffer.Buffer}
+ */
+crypto.DiffieHellman.prototype.generateKeys =
+function(encoding) {};
+
+/**
+ * @param {string|buffer.Buffer} key
+ * @param {string=} inEnc
+ * @param {string=} outEnc
+ * @return {string|buffer.Buffer}
+ */
+crypto.DiffieHellman.prototype.computeSecret =
+function(key, inEnc, outEnc) {};
+
+/**
+ * @param {string=} encoding
+ * @return {string|buffer.Buffer}
+ */
+crypto.DiffieHellman.prototype.getPrime =
+function(encoding) {};
+
+/**
+ * @param {string=} encoding
+ * @return {string|buffer.Buffer}
+ */
+crypto.DiffieHellman.prototype.getGenerator =
+function(encoding) {};
+
+/**
+ * @param {string=} encoding
+ * @return {string|buffer.Buffer}
+ */
+crypto.DiffieHellman.prototype.getPublicKey =
+function(encoding) {};
+
+/**
+ * @param {string} encoding
+ * @return {string|buffer.Buffer}
+ */
+crypto.DiffieHellman.prototype.getPrivateKey =
+function(encoding) {}
+
+/**
+ * @param {string|buffer.Buffer} key
+ * @param {string=} encoding
+ * @return {crypto.DiffieHellman}
+ */
+crypto.DiffieHellman.prototype.setPublicKey =
+function(key, encoding) {};
+
+/**
+ * @param {string|buffer.Buffer} key
+ * @param {string=} encoding
+ * @return {crypto.DiffieHellman}
+ */
+crypto.DiffieHellman.prototype.setPrivateKey =
+function(key, encoding) {};
+
+/**
+ * Note: DiffieHellmanGroup mixes DiffieHellman but doesn't inherit directly.
+ *
+ * @param {string} name
+ * @constructor
+ */
+crypto.DiffieHellmanGroup =
+function(name) {};
+
+/**
+ * @param {string=} encoding
+ * @return {string|buffer.Buffer}
+ */
+crypto.DiffieHellmanGroup.prototype.generateKeys =
+function(encoding) {};
+
+/**
+ * @param {string|buffer.Buffer} key
+ * @param {string=} inEnc
+ * @param {string=} outEnc
+ * @return {string|buffer.Buffer}
+ */
+crypto.DiffieHellmanGroup.prototype.computeSecret =
+function(key, inEnc, outEnc) {};
+
+/**
+ * @param {string=} encoding
+ * @return {string|buffer.Buffer}
+ */
+crypto.DiffieHellmanGroup.prototype.getPrime =
+function(encoding) {};
+
+/**
+ * @param {string=} encoding
+ * @return {string|buffer.Buffer}
+ */
+crypto.DiffieHellmanGroup.prototype.getGenerator =
+function(encoding) {};
+
+/**
+ * @param {string=} encoding
+ * @return {string|buffer.Buffer}
+ */
+crypto.DiffieHellmanGroup.prototype.getPublicKey =
+function(encoding) {};
+
+/**
+ * @param {string} encoding
+ * @return {string|buffer.Buffer}
+ */
+crypto.DiffieHellmanGroup.prototype.getPrivateKey =
+function(encoding) {}
+
+/**
+ * @param {string|buffer.Buffer} key
+ * @param {string=} encoding
+ * @return {crypto.DiffieHellmanGroup}
+ */
+crypto.DiffieHellmanGroup.prototype.setPublicKey =
+function(key, encoding) {};
+
+/**
+ * @param {string|buffer.Buffer} key
+ * @param {string=} encoding
+ * @return {crypto.DiffieHellmanGroup}
+ */
+crypto.DiffieHellmanGroup.prototype.setPrivateKey =
+function(key, encoding) {};
+
+/**
+ * @param {string} group_name
+ * @return {crypto.DiffieHellmanGroup}
+ */
+crypto.getDiffieHellman =
+function(group_name) {};
+
+/**
+ * @param {string|buffer.Buffer} password
+ * @param {string|buffer.Buffer} salt
+ * @param {number} iterations
+ * @param {number} keylen
+ * @param {
+function(*, string)} callback
+ */
+crypto.pbkdf2 =
+function(password, salt, iterations, keylen, callback) {};
+
+/**
+ * @param {string|buffer.Buffer} password
+ * @param {string|buffer.Buffer} salt
+ * @param {number} iterations
+ * @param {number} keylen
+ */
+crypto.pbkdf2Sync =
+function(password, salt, iterations, keylen) {};
+
+/**
+ * @param {number} size
+ * @param {
+function(Error, buffer.Buffer)=} callback
+ */
+crypto.randomBytes =
+function(size, callback) {};
+
+/**
+ * @param {number} size
+ * @param {
+function(Error, buffer.Buffer)=} callback
+ */
+crypto.pseudoRandomBytes =
+function(size, callback) {};
+
+/**
+ * @param {number} size
+ * @param {
+function(Error, buffer.Buffer)=} callback
+ */
+crypto.rng =
+function(size, callback) {};
+
+/**
+ * @param {number} size
+ * @param {
+function(Error, buffer.Buffer)=} callback
+ */
+crypto.prng =
+function(size, callback) {};
+
+/**
+ * @return {Array.}
+ */
+crypto.getCiphers =
+function() {};
+
+/**
+ * @return {Array.}
+ */
+crypto.getHashes =
+function() {};
diff --git a/closure-externs/net.js b/closure-externs/net.js
new file mode 100644
index 0000000..3bfcce8
--- /dev/null
+++ b/closure-externs/net.js
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2012 The Closure Compiler Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for node's net module. Depends on the events and buffer modules.
+ * @see http://nodejs.org/api/net.html
+ * @see https://github.com/joyent/node/blob/master/lib/net.js
+ * @externs
+ * @author Daniel Wirtz
+ */
+
+/**
+ BEGIN_NODE_INCLUDE
+ var net = require('net');
+ END_NODE_INCLUDE
+ */
+
+/**
+ * @type {Object.}
+ */
+var net = {};
+
+/**
+ * @typedef {{allowHalfOpen: ?boolean}}
+ */
+net.CreateOptions;
+
+/**
+ * @param {(net.CreateOptions|
+function(...))=} options
+ * @param {
+function(...)=} connectionListener
+ * @return {net.Server}
+ */
+net.createServer =
+function(options, connectionListener) {};
+
+/**
+ * @typedef {{port: ?number, host: ?string, localAddress: ?string, path: ?string, allowHalfOpen: ?boolean}}
+ */
+net.ConnectOptions;
+
+/**
+ * @param {net.ConnectOptions|number|string} arg1
+ * @param {(
+function(...)|string)=} arg2
+ * @param {
+function(...)=} arg3
+ */
+net.connect =
+function(arg1, arg2, arg3) {};
+
+/**
+ * @param {net.ConnectOptions|number|string} arg1
+ * @param {(
+function(...)|string)=} arg2
+ * @param {
+function(...)=} arg3
+ */
+net.createConnection =
+function(arg1, arg2, arg3) {};
+
+/**
+ * @constructor
+ * @extends events.EventEmitter
+ */
+net.Server =
+function() {};
+
+/**
+ *
+ * @param {number|*} port
+ * @param {(string|number|
+function(...))=} host
+ * @param {(number|
+function(...))=} backlog
+ * @param {
+function(...)=} callback
+ */
+net.Server.prototype.listen =
+function(port, host, backlog, callback) {};
+
+/**
+ * @param {
+function(...)=} callback
+ */
+net.Server.prototype.close =
+function(callback) {};
+
+/**
+ * @return {{port: number, family: string, address: string}}
+ */
+net.Server.prototype.address =
+function() {};
+
+/**
+ * @type {number}
+ */
+net.Server.prototype.maxConnectinos;
+
+/**
+ * @type {number}
+ */
+net.Server.prototype.connections;
+
+/**
+ * @constructor
+ * @param {{fd: ?*, type: ?string, allowHalfOpen: ?boolean}=} options
+ * @extends events.EventEmitter
+ */
+net.Socket =
+function(options) {};
+
+/**
+ * @param {number|string|
+function(...)} port
+ * @param {(string|
+function(...))=} host
+ * @param {
+function(...)=} connectListener
+ */
+net.Socket.prototype.connect =
+function(port, host, connectListener) {};
+
+/**
+ * @type {number}
+ */
+net.Socket.prototype.bufferSize;
+
+/**
+ * @param {?string=} encoding
+ */
+net.Socket.prototype.setEncoding =
+function (encoding) { };
+net.Socket.prototype.on =
+function (str, func) { };
+
+/**
+ * @param {string|buffer.Buffer} data
+ * @param {(string|
+function(...))=}encoding
+ * @param {
+function(...)=} callback
+ */
+net.Socket.prototype.write =
+function(data, encoding, callback) {};
+
+/**
+ * @param {(string|buffer.Buffer)=}data
+ * @param {string=} encoding
+ */
+net.Socket.prototype.end =
+function(data, encoding) {};
+
+/**
+ */
+net.Socket.prototype.destroy =
+function() {};
+
+/**
+ */
+net.Socket.prototype.pause =
+function() {};
+
+/**
+ */
+net.Socket.prototype.resume =
+function() {};
+
+/**
+ * @param {number} timeout
+ * @param {
+function(...)=} callback
+ */
+net.Socket.prototype.setTimeout =
+function(timeout, callback) {};
+
+/**
+ * @param {boolean=} noDelay
+ */
+net.Socket.prototype.setNoDelay =
+function(noDelay) {};
+
+/**
+ * @param {(boolean|number)=} enable
+ * @param {number=} initialDelay
+ */
+net.Socket.prototype.setKeepAlive =
+function(enable, initialDelay) {};
+
+/**
+ * @return {string}
+ */
+net.Socket.prototype.address =
+function() {};
+
+/**
+ * @type {?string}
+ */
+net.Socket.prototype.remoteAddress;
+
+/**
+ * @type {?number}
+ */
+net.Socket.prototype.remotePort;
+
+/**
+ * @type {number}
+ */
+net.Socket.prototype.bytesRead;
+
+/**
+ * @type {number}
+ */
+net.Socket.prototype.bytesWritten;
+
+/**
+ * @param {*} input
+ * @return {number}
+ */
+net.isIP =
+function(input) {};
+
+/**
+ * @param {*} input
+ * @return {boolean}
+ */
+net.isIPv4 =
+function(input) {};
+
+/**
+ * @param {*} input
+ * @return {boolean}
+ */
+net.isIPv6 =
+function(input) {};
diff --git a/closure-externs/tls.js b/closure-externs/tls.js
new file mode 100644
index 0000000..9ff4345
--- /dev/null
+++ b/closure-externs/tls.js
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2012 The Closure Compiler Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for node's tls module. Depends on the stream module.
+ * @see http://nodejs.org/api/tls.html
+ * @see https://github.com/joyent/node/blob/master/lib/tls.js
+ * @externs
+ * @author Daniel Wirtz
+ */
+
+/**
+ BEGIN_NODE_INCLUDE
+ var tls = require('tls');
+ END_NODE_INCLUDE
+ */
+
+/**
+ * @type {Object.}
+ */
+var tls = {};
+
+/**
+ * @typedef {{pfx: (string|buffer.Buffer), key: (string|buffer.Buffer), passphrase: string, cert: (string|buffer.Buffer), ca: Array., crl: (string|Array.), ciphers: string, honorCipherOrder: boolean, requestCert: boolean, rejectUnauthorized: boolean, NPNProtocols: (Array|buffer.Buffer), SNICallback:
+function(string), sessionIdContext: string}}
+ */
+tls.CreateOptions;
+
+/**
+ *
+ * @param {tls.CreateOptions} options
+ * @param {
+function(...)=} secureConnectionListener
+ * @return {tls.Server}
+ */
+tls.createServer =
+function(options, secureConnectionListener) {};
+
+/**
+ * @typedef {{host: string, port: number, socket: *, pfx: (string|buffer.Buffer), key: (string|buffer.Buffer), passphrase: string, cert: (string|buffer.Buffer), ca: Array., rejectUnauthorized: boolean, NPNProtocols: Array., servername: string}}
+ */
+tls.ConnectOptions;
+
+/**
+ *
+ * @param {number|tls.ConnectOptions} port
+ * @param {(string|tls.ConnectOptions|
+function(...))=} host
+ * @param {(tls.ConnectOptions|
+function(...))=} options
+ * @param {
+function(...)=} callback
+ */
+tls.connect =
+function(port, host, options, callback) {};
+
+/**
+ * @param {crypto.Credentials=} credentials
+ * @param {boolean=} isServer
+ * @param {boolean=} requestCert
+ * @param {boolean=} rejectUnauthorized
+ * @return {tls.SecurePair}
+ */
+tls.createSecurePair =
+function(credentials, isServer, requestCert, rejectUnauthorized) {};
+
+/**
+ * @constructor
+ * @extends events.EventEmitter
+ */
+tls.SecurePair =
+function() {};
+
+/**
+ * @constructor
+ * @extends net.Server
+ */
+tls.Server =
+function() {};
+
+/**
+ * @param {string} hostname
+ * @param {string|buffer.Buffer} credentials
+ */
+tls.Server.prototype.addContext =
+function(hostname, credentials) {};
+
+/**
+ * @constructor
+ * @extends stream.Duplex
+ */
+tls.CleartextStream =
+function() {};
+
+/**
+ * @type {boolean}
+ */
+tls.CleartextStream.prototype.authorized;
+
+/**
+ * @type {?string}
+ */
+tls.CleartextStream.prototype.authorizationError;
+
+/**
+ * @return {Object.)>}
+ */
+tls.CleartextStream.prototype.getPeerCertificate =
+function() {};
+
+/**
+ * @return {{name: string, version: string}}
+ */
+tls.CleartextStream.prototype.getCipher =
+function() {};
+
+/**
+ * @return {{port: number, family: string, address: string}}
+ */
+tls.CleartextStream.prototype.address =
+function() {};
+
+/**
+ * @type {string}
+ */
+tls.CleartextStream.prototype.remoteAddress;
+
+/**
+ * @type {number}
+ */
+tls.CleartextStream.prototype.remotePort;
diff --git a/common-0.0.1.js b/common-0.0.1.js
new file mode 100644
index 0000000..b228e3b
--- /dev/null
+++ b/common-0.0.1.js
@@ -0,0 +1,105 @@
+/**
+* @description Set of short commonly used methods for handling HTML elements
+* @author Ylian Saint-Hilaire
+* @version v0.0.1b
+*/
+
+// Add startsWith for IE browser
+if (!String.prototype.startsWith) { String.prototype.startsWith = function (str) { return this.lastIndexOf(str, 0) === 0; }; }
+if (!String.prototype.endsWith) { String.prototype.endsWith = function (str) { return this.indexOf(str, this.length - str.length) !== -1; }; }
+
+// Quick UI functions, a bit of a replacement for jQuery
+//function Q(x) { if (document.getElementById(x) == null) { console.log('Invalid element: ' + x); } return document.getElementById(x); } // "Q"
+function Q(x) { return document.getElementById(x); } // "Q"
+function QS(x) { try { return Q(x).style; } catch (x) { } } // "Q" style
+function QE(x, y) { try { Q(x).disabled = !y; } catch (x) { } } // "Q" enable
+function QV(x, y) { try { QS(x).display = (y ? '' : 'none'); } catch (x) { } } // "Q" visible
+function QA(x, y) { Q(x).innerHTML += y; } // "Q" append
+function QH(x, y) { Q(x).innerHTML = y; } // "Q" html
+
+// Move cursor to end of input box
+function inputBoxFocus(x) { Q(x).focus(); var v = Q(x).value; Q(x).value = ''; Q(x).value = v; }
+
+// Binary encoding and decoding functions
+function ReadShort(v, p) { return (v.charCodeAt(p) << 8) + v.charCodeAt(p + 1); }
+function ReadShortX(v, p) { return (v.charCodeAt(p + 1) << 8) + v.charCodeAt(p); }
+function ReadInt(v, p) { return (v.charCodeAt(p) * 0x1000000) + (v.charCodeAt(p + 1) << 16) + (v.charCodeAt(p + 2) << 8) + v.charCodeAt(p + 3); } // We use "*0x1000000" instead of "<<24" because the shift converts the number to signed int32.
+function ReadSInt(v, p) { return (v.charCodeAt(p) << 24) + (v.charCodeAt(p + 1) << 16) + (v.charCodeAt(p + 2) << 8) + v.charCodeAt(p + 3); }
+function ReadIntX(v, p) { return (v.charCodeAt(p + 3) * 0x1000000) + (v.charCodeAt(p + 2) << 16) + (v.charCodeAt(p + 1) << 8) + v.charCodeAt(p); }
+function ShortToStr(v) { return String.fromCharCode((v >> 8) & 0xFF, v & 0xFF); }
+function ShortToStrX(v) { return String.fromCharCode(v & 0xFF, (v >> 8) & 0xFF); }
+function IntToStr(v) { return String.fromCharCode((v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF); }
+function IntToStrX(v) { return String.fromCharCode(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF, (v >> 24) & 0xFF); }
+function MakeToArray(v) { if (!v || v == null || typeof v == 'object') return v; return [v]; }
+function SplitArray(v) { return v.split(','); }
+function Clone(v) { return JSON.parse(JSON.stringify(v)); }
+function EscapeHtml(x) { if (typeof x == "string") return x.replace(/&/g, '&').replace(/>/g, '>').replace(/' + gap(c) + "Item #" + i + ": " + ObjectToStringEx(x[i], c + 1); } }
+ else if (x instanceof Object) { for (var i in x) { r += ' ' + gap(c) + i + " = " + ObjectToStringEx(x[i], c + 1); } }
+ else { r += EscapeHtml(x); }
+ return r;
+}
+
+// Print object for console
+function ObjectToStringEx2(x, c) {
+ var r = "";
+ if (x != 0 && (!x || x == null)) return "(Null)";
+ if (x instanceof Array) { for (var i in x) { r += '\r\n' + gap2(c) + "Item #" + i + ": " + ObjectToStringEx2(x[i], c + 1); } }
+ else if (x instanceof Object) { for (var i in x) { r += '\r\n' + gap2(c) + i + " = " + ObjectToStringEx2(x[i], c + 1); } }
+ else { r += EscapeHtml(x); }
+ return r;
+}
+
+// Create an ident gap
+function gap(c) { var x = ''; for (var i = 0; i < (c * 4) ; i++) { x += ' '; } return x; }
+function gap2(c) { var x = ''; for (var i = 0; i < (c * 4) ; i++) { x += ' '; } return x; }
+
+// Print an object in html
+function ObjectToString(x) { return ObjectToStringEx(x, 0); }
+function ObjectToString2(x) { return ObjectToStringEx2(x, 0); }
+
+// Convert a hex string to a raw string
+function hex2rstr(d) {
+ if (typeof d != "string" || d.length == 0) return '';
+ var r = '', m = ('' + d).match(/../g), t;
+ while (t = m.shift()) r += String.fromCharCode('0x' + t);
+ return r
+}
+
+// Convert decimal to hex
+function char2hex(i) { return (i + 0x100).toString(16).substr(-2).toUpperCase(); }
+
+// Convert a raw string to a hex string
+function rstr2hex(input) {
+ var r = '', i;
+ for (i = 0; i < input.length; i++) { r += char2hex(input.charCodeAt(i)); }
+ return r;
+}
+
+// UTF-8 encoding & decoding functions
+function encode_utf8(s) { return unescape(encodeURIComponent(s)); }
+function decode_utf8(s) { return decodeURIComponent(escape(s)); }
+
+// Convert a string into a blob
+function data2blob(data) {
+ var bytes = new Array(data.length);
+ for (var i = 0; i < data.length; i++) bytes[i] = data.charCodeAt(i);
+ var blob = new Blob([new Uint8Array(bytes)]);
+ return blob;
+}
+
+// Generate random numbers
+function random(max) { return Math.floor(Math.random() * max); }
+
+// Trademarks
+function trademarks(x) { return x.replace(/\(R\)/g, '®').replace(/\(TM\)/g, '™'); }
+
+
diff --git a/desktop.ini b/desktop.ini
new file mode 100644
index 0000000..2465586
--- /dev/null
+++ b/desktop.ini
@@ -0,0 +1,2 @@
+[LocalizedFileNames]
+Changes.txt=@Changes.txt,0
diff --git a/favicon-intel.ico b/favicon-intel.ico
new file mode 100644
index 0000000..60c8c85
Binary files /dev/null and b/favicon-intel.ico differ
diff --git a/favicon-intel.png b/favicon-intel.png
new file mode 100644
index 0000000..365e308
Binary files /dev/null and b/favicon-intel.png differ
diff --git a/favicon.ico b/favicon.ico
new file mode 100644
index 0000000..28f4caa
Binary files /dev/null and b/favicon.ico differ
diff --git a/favicon.png b/favicon.png
new file mode 100644
index 0000000..5aeb966
Binary files /dev/null and b/favicon.png differ
diff --git a/filesaver.1.1.20151003.js b/filesaver.1.1.20151003.js
new file mode 100644
index 0000000..f441c22
--- /dev/null
+++ b/filesaver.1.1.20151003.js
@@ -0,0 +1,270 @@
+/* FileSaver.js
+ * A saveAs() FileSaver implementation.
+ * 1.1.20151003
+ *
+ * By Eli Grey, http://eligrey.com
+ * License: MIT
+ * See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
+ */
+
+/*global self */
+/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
+
+/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
+
+var saveAs = saveAs || (function (view) {
+ "use strict";
+ // IE <10 is explicitly unsupported
+ if (typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) {
+ return;
+ }
+ var
+ doc = view.document
+ // only get URL when necessary in case Blob.js hasn't overridden it yet
+ , get_URL = function () {
+ return view.URL || view.webkitURL || view;
+ }
+ , save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
+ , can_use_save_link = "download" in save_link
+ , click = function (node) {
+ var event = new MouseEvent("click");
+ node.dispatchEvent(event);
+ }
+ , is_safari = /Version\/[\d\.]+.*Safari/.test(navigator.userAgent)
+ , webkit_req_fs = view.webkitRequestFileSystem
+ , req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
+ , throw_outside = function (ex) {
+ (view.setImmediate || view.setTimeout)(function () {
+ throw ex;
+ }, 0);
+ }
+ , force_saveable_type = "application/octet-stream"
+ , fs_min_size = 0
+ // See https://code.google.com/p/chromium/issues/detail?id=375297#c7 and
+ // https://github.com/eligrey/FileSaver.js/commit/485930a#commitcomment-8768047
+ // for the reasoning behind the timeout and revocation flow
+ , arbitrary_revoke_timeout = 500 // in ms
+ , revoke = function (file) {
+ var revoker = function () {
+ if (typeof file === "string") { // file is an object URL
+ get_URL().revokeObjectURL(file);
+ } else { // file is a File
+ file.remove();
+ }
+ };
+ if (view.chrome) {
+ revoker();
+ } else {
+ setTimeout(revoker, arbitrary_revoke_timeout);
+ }
+ }
+ , dispatch = function (filesaver, event_types, event) {
+ event_types = [].concat(event_types);
+ var i = event_types.length;
+ while (i--) {
+ var listener = filesaver["on" + event_types[i]];
+ if (typeof listener === "function") {
+ try {
+ listener.call(filesaver, event || filesaver);
+ } catch (ex) {
+ throw_outside(ex);
+ }
+ }
+ }
+ }
+ , auto_bom = function (blob) {
+ // prepend BOM for UTF-8 XML and text types (including HTML)
+ if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
+ return new Blob(["\ufeff", blob], { type: blob.type });
+ }
+ return blob;
+ }
+ , FileSaver = function (blob, name, no_auto_bom) {
+ if (!no_auto_bom) {
+ blob = auto_bom(blob);
+ }
+ // First try a.download, then web filesystem, then object URLs
+ var
+ filesaver = this
+ , type = blob.type
+ , blob_changed = false
+ , object_url
+ , target_view
+ , dispatch_all = function () {
+ dispatch(filesaver, "writestart progress write writeend".split(" "));
+ }
+ // on any filesys errors revert to saving with object URLs
+ , fs_error = function () {
+ if (target_view && is_safari && typeof FileReader !== "undefined") {
+ // Safari doesn't allow downloading of blob urls
+ var reader = new FileReader();
+ reader.onloadend = function () {
+ var base64Data = reader.result;
+ target_view.location.href = "data:attachment/file" + base64Data.slice(base64Data.search(/[,;]/));
+ filesaver.readyState = filesaver.DONE;
+ dispatch_all();
+ };
+ reader.readAsDataURL(blob);
+ filesaver.readyState = filesaver.INIT;
+ return;
+ }
+ // don't create more object URLs than needed
+ if (blob_changed || !object_url) {
+ object_url = get_URL().createObjectURL(blob);
+ }
+ if (target_view) {
+ target_view.location.href = object_url;
+ } else {
+ var new_tab = view.open(object_url, "_blank");
+ if (new_tab == undefined && is_safari) {
+ //Apple do not allow window.open, see http://bit.ly/1kZffRI
+ view.location.href = object_url
+ }
+ }
+ filesaver.readyState = filesaver.DONE;
+ dispatch_all();
+ revoke(object_url);
+ }
+ , abortable = function (func) {
+ return function () {
+ if (filesaver.readyState !== filesaver.DONE) {
+ return func.apply(this, arguments);
+ }
+ };
+ }
+ , create_if_not_found = { create: true, exclusive: false }
+ , slice
+ ;
+ filesaver.readyState = filesaver.INIT;
+ if (!name) {
+ name = "download";
+ }
+ if (can_use_save_link) {
+ object_url = get_URL().createObjectURL(blob);
+ save_link.href = object_url;
+ save_link.download = name;
+ setTimeout(function () {
+ click(save_link);
+ dispatch_all();
+ revoke(object_url);
+ filesaver.readyState = filesaver.DONE;
+ });
+ return;
+ }
+ // Object and web filesystem URLs have a problem saving in Google Chrome when
+ // viewed in a tab, so I force save with application/octet-stream
+ // http://code.google.com/p/chromium/issues/detail?id=91158
+ // Update: Google errantly closed 91158, I submitted it again:
+ // https://code.google.com/p/chromium/issues/detail?id=389642
+ if (view.chrome && type && type !== force_saveable_type) {
+ slice = blob.slice || blob.webkitSlice;
+ blob = slice.call(blob, 0, blob.size, force_saveable_type);
+ blob_changed = true;
+ }
+ // Since I can't be sure that the guessed media type will trigger a download
+ // in WebKit, I append .download to the filename.
+ // https://bugs.webkit.org/show_bug.cgi?id=65440
+ if (webkit_req_fs && name !== "download") {
+ name += ".download";
+ }
+ if (type === force_saveable_type || webkit_req_fs) {
+ target_view = view;
+ }
+ if (!req_fs) {
+ fs_error();
+ return;
+ }
+ fs_min_size += blob.size;
+ req_fs(view.TEMPORARY, fs_min_size, abortable(function (fs) {
+ fs.root.getDirectory("saved", create_if_not_found, abortable(function (dir) {
+ var save = function () {
+ dir.getFile(name, create_if_not_found, abortable(function (file) {
+ file.createWriter(abortable(function (writer) {
+ writer.onwriteend = function (event) {
+ target_view.location.href = file.toURL();
+ filesaver.readyState = filesaver.DONE;
+ dispatch(filesaver, "writeend", event);
+ revoke(file);
+ };
+ writer.onerror = function () {
+ var error = writer.error;
+ if (error.code !== error.ABORT_ERR) {
+ fs_error();
+ }
+ };
+ "writestart progress write abort".split(" ").forEach(function (event) {
+ writer["on" + event] = filesaver["on" + event];
+ });
+ writer.write(blob);
+ filesaver.abort = function () {
+ writer.abort();
+ filesaver.readyState = filesaver.DONE;
+ };
+ filesaver.readyState = filesaver.WRITING;
+ }), fs_error);
+ }), fs_error);
+ };
+ dir.getFile(name, { create: false }, abortable(function (file) {
+ // delete file if it already exists
+ file.remove();
+ save();
+ }), abortable(function (ex) {
+ if (ex.code === ex.NOT_FOUND_ERR) {
+ save();
+ } else {
+ fs_error();
+ }
+ }));
+ }), fs_error);
+ }), fs_error);
+ }
+ , FS_proto = FileSaver.prototype
+ , saveAs = function (blob, name, no_auto_bom) {
+ return new FileSaver(blob, name, no_auto_bom);
+ }
+ ;
+ // IE 10+ (native saveAs)
+ if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
+ return function (blob, name, no_auto_bom) {
+ if (!no_auto_bom) {
+ blob = auto_bom(blob);
+ }
+ return navigator.msSaveOrOpenBlob(blob, name || "download");
+ };
+ }
+
+ FS_proto.abort = function () {
+ var filesaver = this;
+ filesaver.readyState = filesaver.DONE;
+ dispatch(filesaver, "abort");
+ };
+ FS_proto.readyState = FS_proto.INIT = 0;
+ FS_proto.WRITING = 1;
+ FS_proto.DONE = 2;
+
+ FS_proto.error =
+ FS_proto.onwritestart =
+ FS_proto.onprogress =
+ FS_proto.onwrite =
+ FS_proto.onabort =
+ FS_proto.onerror =
+ FS_proto.onwriteend =
+ null;
+
+ return saveAs;
+}(
+ typeof self !== "undefined" && self
+ || typeof window !== "undefined" && window
+ || this.content
+));
+// `self` is undefined in Firefox for Android content script context
+// while `this` is nsIContentFrameMessageManager
+// with an attribute `content` that corresponds to the window
+
+if (typeof module !== "undefined" && module.exports) {
+ module.exports.saveAs = saveAs;
+} else if ((typeof define !== "undefined" && define !== null) && (define.amd != null)) {
+ define([], function () {
+ return saveAs;
+ });
+}
\ No newline at end of file
diff --git a/forge.js/aes.js b/forge.js/aes.js
new file mode 100644
index 0000000..d16fc34
--- /dev/null
+++ b/forge.js/aes.js
@@ -0,0 +1,1147 @@
+/**
+ * Advanced Encryption Standard (AES) implementation.
+ *
+ * This implementation is based on the public domain library 'jscrypto' which
+ * was written by:
+ *
+ * Emily Stark (estark@stanford.edu)
+ * Mike Hamburg (mhamburg@stanford.edu)
+ * Dan Boneh (dabo@cs.stanford.edu)
+ *
+ * Parts of this code are based on the OpenSSL implementation of AES:
+ * http://www.openssl.org
+ *
+ * @author Dave Longley
+ *
+ * Copyright (c) 2010-2014 Digital Bazaar, Inc.
+ */
+(function() {
+/* ########## Begin module implementation ########## */
+function initModule(forge) {
+
+/* AES API */
+forge.aes = forge.aes || {};
+
+/**
+ * Deprecated. Instead, use:
+ *
+ * var cipher = forge.cipher.createCipher('AES-', key);
+ * cipher.start({iv: iv});
+ *
+ * Creates an AES cipher object to encrypt data using the given symmetric key.
+ * The output will be stored in the 'output' member of the returned cipher.
+ *
+ * The key and iv may be given as a string of bytes, an array of bytes,
+ * a byte buffer, or an array of 32-bit words.
+ *
+ * @param key the symmetric key to use.
+ * @param iv the initialization vector to use.
+ * @param output the buffer to write to, null to create one.
+ * @param mode the cipher mode to use (default: 'CBC').
+ *
+ * @return the cipher.
+ */
+forge.aes.startEncrypting = function(key, iv, output, mode) {
+ var cipher = _createCipher({
+ key: key,
+ output: output,
+ decrypt: false,
+ mode: mode
+ });
+ cipher.start(iv);
+ return cipher;
+};
+
+/**
+ * Deprecated. Instead, use:
+ *
+ * var cipher = forge.cipher.createCipher('AES-', key);
+ *
+ * Creates an AES cipher object to encrypt data using the given symmetric key.
+ *
+ * The key may be given as a string of bytes, an array of bytes, a
+ * byte buffer, or an array of 32-bit words.
+ *
+ * @param key the symmetric key to use.
+ * @param mode the cipher mode to use (default: 'CBC').
+ *
+ * @return the cipher.
+ */
+forge.aes.createEncryptionCipher = function(key, mode) {
+ return _createCipher({
+ key: key,
+ output: null,
+ decrypt: false,
+ mode: mode
+ });
+};
+
+/**
+ * Deprecated. Instead, use:
+ *
+ * var decipher = forge.cipher.createDecipher('AES-', key);
+ * decipher.start({iv: iv});
+ *
+ * Creates an AES cipher object to decrypt data using the given symmetric key.
+ * The output will be stored in the 'output' member of the returned cipher.
+ *
+ * The key and iv may be given as a string of bytes, an array of bytes,
+ * a byte buffer, or an array of 32-bit words.
+ *
+ * @param key the symmetric key to use.
+ * @param iv the initialization vector to use.
+ * @param output the buffer to write to, null to create one.
+ * @param mode the cipher mode to use (default: 'CBC').
+ *
+ * @return the cipher.
+ */
+forge.aes.startDecrypting = function(key, iv, output, mode) {
+ var cipher = _createCipher({
+ key: key,
+ output: output,
+ decrypt: true,
+ mode: mode
+ });
+ cipher.start(iv);
+ return cipher;
+};
+
+/**
+ * Deprecated. Instead, use:
+ *
+ * var decipher = forge.cipher.createDecipher('AES-', key);
+ *
+ * Creates an AES cipher object to decrypt data using the given symmetric key.
+ *
+ * The key may be given as a string of bytes, an array of bytes, a
+ * byte buffer, or an array of 32-bit words.
+ *
+ * @param key the symmetric key to use.
+ * @param mode the cipher mode to use (default: 'CBC').
+ *
+ * @return the cipher.
+ */
+forge.aes.createDecryptionCipher = function(key, mode) {
+ return _createCipher({
+ key: key,
+ output: null,
+ decrypt: true,
+ mode: mode
+ });
+};
+
+/**
+ * Creates a new AES cipher algorithm object.
+ *
+ * @param name the name of the algorithm.
+ * @param mode the mode factory function.
+ *
+ * @return the AES algorithm object.
+ */
+forge.aes.Algorithm = function(name, mode) {
+ if(!init) {
+ initialize();
+ }
+ var self = this;
+ self.name = name;
+ self.mode = new mode({
+ blockSize: 16,
+ cipher: {
+ encrypt: function(inBlock, outBlock) {
+ return _updateBlock(self._w, inBlock, outBlock, false);
+ },
+ decrypt: function(inBlock, outBlock) {
+ return _updateBlock(self._w, inBlock, outBlock, true);
+ }
+ }
+ });
+ self._init = false;
+};
+
+/**
+ * Initializes this AES algorithm by expanding its key.
+ *
+ * @param options the options to use.
+ * key the key to use with this algorithm.
+ * decrypt true if the algorithm should be initialized for decryption,
+ * false for encryption.
+ */
+forge.aes.Algorithm.prototype.initialize = function(options) {
+ if(this._init) {
+ return;
+ }
+
+ var key = options.key;
+ var tmp;
+
+ /* Note: The key may be a string of bytes, an array of bytes, a byte
+ buffer, or an array of 32-bit integers. If the key is in bytes, then
+ it must be 16, 24, or 32 bytes in length. If it is in 32-bit
+ integers, it must be 4, 6, or 8 integers long. */
+
+ if(typeof key === 'string' &&
+ (key.length === 16 || key.length === 24 || key.length === 32)) {
+ // convert key string into byte buffer
+ key = forge.util.createBuffer(key);
+ } else if(forge.util.isArray(key) &&
+ (key.length === 16 || key.length === 24 || key.length === 32)) {
+ // convert key integer array into byte buffer
+ tmp = key;
+ key = forge.util.createBuffer();
+ for(var i = 0; i < tmp.length; ++i) {
+ key.putByte(tmp[i]);
+ }
+ }
+
+ // convert key byte buffer into 32-bit integer array
+ if(!forge.util.isArray(key)) {
+ tmp = key;
+ key = [];
+
+ // key lengths of 16, 24, 32 bytes allowed
+ var len = tmp.length();
+ if(len === 16 || len === 24 || len === 32) {
+ len = len >>> 2;
+ for(var i = 0; i < len; ++i) {
+ key.push(tmp.getInt32());
+ }
+ }
+ }
+
+ // key must be an array of 32-bit integers by now
+ if(!forge.util.isArray(key) ||
+ !(key.length === 4 || key.length === 6 || key.length === 8)) {
+ throw new Error('Invalid key parameter.');
+ }
+
+ // encryption operation is always used for these modes
+ var mode = this.mode.name;
+ var encryptOp = (['CFB', 'OFB', 'CTR', 'GCM'].indexOf(mode) !== -1);
+
+ // do key expansion
+ this._w = _expandKey(key, options.decrypt && !encryptOp);
+ this._init = true;
+};
+
+/**
+ * Expands a key. Typically only used for testing.
+ *
+ * @param key the symmetric key to expand, as an array of 32-bit words.
+ * @param decrypt true to expand for decryption, false for encryption.
+ *
+ * @return the expanded key.
+ */
+forge.aes._expandKey = function(key, decrypt) {
+ if(!init) {
+ initialize();
+ }
+ return _expandKey(key, decrypt);
+};
+
+/**
+ * Updates a single block. Typically only used for testing.
+ *
+ * @param w the expanded key to use.
+ * @param input an array of block-size 32-bit words.
+ * @param output an array of block-size 32-bit words.
+ * @param decrypt true to decrypt, false to encrypt.
+ */
+forge.aes._updateBlock = _updateBlock;
+
+
+/** Register AES algorithms **/
+
+registerAlgorithm('AES-ECB', forge.cipher.modes.ecb);
+registerAlgorithm('AES-CBC', forge.cipher.modes.cbc);
+registerAlgorithm('AES-CFB', forge.cipher.modes.cfb);
+registerAlgorithm('AES-OFB', forge.cipher.modes.ofb);
+registerAlgorithm('AES-CTR', forge.cipher.modes.ctr);
+registerAlgorithm('AES-GCM', forge.cipher.modes.gcm);
+
+function registerAlgorithm(name, mode) {
+ var factory = function() {
+ return new forge.aes.Algorithm(name, mode);
+ };
+ forge.cipher.registerAlgorithm(name, factory);
+}
+
+
+/** AES implementation **/
+
+var init = false; // not yet initialized
+var Nb = 4; // number of words comprising the state (AES = 4)
+var sbox; // non-linear substitution table used in key expansion
+var isbox; // inversion of sbox
+var rcon; // round constant word array
+var mix; // mix-columns table
+var imix; // inverse mix-columns table
+
+/**
+ * Performs initialization, ie: precomputes tables to optimize for speed.
+ *
+ * One way to understand how AES works is to imagine that 'addition' and
+ * 'multiplication' are interfaces that require certain mathematical
+ * properties to hold true (ie: they are associative) but they might have
+ * different implementations and produce different kinds of results ...
+ * provided that their mathematical properties remain true. AES defines
+ * its own methods of addition and multiplication but keeps some important
+ * properties the same, ie: associativity and distributivity. The
+ * explanation below tries to shed some light on how AES defines addition
+ * and multiplication of bytes and 32-bit words in order to perform its
+ * encryption and decryption algorithms.
+ *
+ * The basics:
+ *
+ * The AES algorithm views bytes as binary representations of polynomials
+ * that have either 1 or 0 as the coefficients. It defines the addition
+ * or subtraction of two bytes as the XOR operation. It also defines the
+ * multiplication of two bytes as a finite field referred to as GF(2^8)
+ * (Note: 'GF' means "Galois Field" which is a field that contains a finite
+ * number of elements so GF(2^8) has 256 elements).
+ *
+ * This means that any two bytes can be represented as binary polynomials;
+ * when they multiplied together and modularly reduced by an irreducible
+ * polynomial of the 8th degree, the results are the field GF(2^8). The
+ * specific irreducible polynomial that AES uses in hexadecimal is 0x11b.
+ * This multiplication is associative with 0x01 as the identity:
+ *
+ * (b * 0x01 = GF(b, 0x01) = b).
+ *
+ * The operation GF(b, 0x02) can be performed at the byte level by left
+ * shifting b once and then XOR'ing it (to perform the modular reduction)
+ * with 0x11b if b is >= 128. Repeated application of the multiplication
+ * of 0x02 can be used to implement the multiplication of any two bytes.
+ *
+ * For instance, multiplying 0x57 and 0x13, denoted as GF(0x57, 0x13), can
+ * be performed by factoring 0x13 into 0x01, 0x02, and 0x10. Then these
+ * factors can each be multiplied by 0x57 and then added together. To do
+ * the multiplication, values for 0x57 multiplied by each of these 3 factors
+ * can be precomputed and stored in a table. To add them, the values from
+ * the table are XOR'd together.
+ *
+ * AES also defines addition and multiplication of words, that is 4-byte
+ * numbers represented as polynomials of 3 degrees where the coefficients
+ * are the values of the bytes.
+ *
+ * The word [a0, a1, a2, a3] is a polynomial a3x^3 + a2x^2 + a1x + a0.
+ *
+ * Addition is performed by XOR'ing like powers of x. Multiplication
+ * is performed in two steps, the first is an algebriac expansion as
+ * you would do normally (where addition is XOR). But the result is
+ * a polynomial larger than 3 degrees and thus it cannot fit in a word. So
+ * next the result is modularly reduced by an AES-specific polynomial of
+ * degree 4 which will always produce a polynomial of less than 4 degrees
+ * such that it will fit in a word. In AES, this polynomial is x^4 + 1.
+ *
+ * The modular product of two polynomials 'a' and 'b' is thus:
+ *
+ * d(x) = d3x^3 + d2x^2 + d1x + d0
+ * with
+ * d0 = GF(a0, b0) ^ GF(a3, b1) ^ GF(a2, b2) ^ GF(a1, b3)
+ * d1 = GF(a1, b0) ^ GF(a0, b1) ^ GF(a3, b2) ^ GF(a2, b3)
+ * d2 = GF(a2, b0) ^ GF(a1, b1) ^ GF(a0, b2) ^ GF(a3, b3)
+ * d3 = GF(a3, b0) ^ GF(a2, b1) ^ GF(a1, b2) ^ GF(a0, b3)
+ *
+ * As a matrix:
+ *
+ * [d0] = [a0 a3 a2 a1][b0]
+ * [d1] [a1 a0 a3 a2][b1]
+ * [d2] [a2 a1 a0 a3][b2]
+ * [d3] [a3 a2 a1 a0][b3]
+ *
+ * Special polynomials defined by AES (0x02 == {02}):
+ * a(x) = {03}x^3 + {01}x^2 + {01}x + {02}
+ * a^-1(x) = {0b}x^3 + {0d}x^2 + {09}x + {0e}.
+ *
+ * These polynomials are used in the MixColumns() and InverseMixColumns()
+ * operations, respectively, to cause each element in the state to affect
+ * the output (referred to as diffusing).
+ *
+ * RotWord() uses: a0 = a1 = a2 = {00} and a3 = {01}, which is the
+ * polynomial x3.
+ *
+ * The ShiftRows() method modifies the last 3 rows in the state (where
+ * the state is 4 words with 4 bytes per word) by shifting bytes cyclically.
+ * The 1st byte in the second row is moved to the end of the row. The 1st
+ * and 2nd bytes in the third row are moved to the end of the row. The 1st,
+ * 2nd, and 3rd bytes are moved in the fourth row.
+ *
+ * More details on how AES arithmetic works:
+ *
+ * In the polynomial representation of binary numbers, XOR performs addition
+ * and subtraction and multiplication in GF(2^8) denoted as GF(a, b)
+ * corresponds with the multiplication of polynomials modulo an irreducible
+ * polynomial of degree 8. In other words, for AES, GF(a, b) will multiply
+ * polynomial 'a' with polynomial 'b' and then do a modular reduction by
+ * an AES-specific irreducible polynomial of degree 8.
+ *
+ * A polynomial is irreducible if its only divisors are one and itself. For
+ * the AES algorithm, this irreducible polynomial is:
+ *
+ * m(x) = x^8 + x^4 + x^3 + x + 1,
+ *
+ * or {01}{1b} in hexadecimal notation, where each coefficient is a bit:
+ * 100011011 = 283 = 0x11b.
+ *
+ * For example, GF(0x57, 0x83) = 0xc1 because
+ *
+ * 0x57 = 87 = 01010111 = x^6 + x^4 + x^2 + x + 1
+ * 0x85 = 131 = 10000101 = x^7 + x + 1
+ *
+ * (x^6 + x^4 + x^2 + x + 1) * (x^7 + x + 1)
+ * = x^13 + x^11 + x^9 + x^8 + x^7 +
+ * x^7 + x^5 + x^3 + x^2 + x +
+ * x^6 + x^4 + x^2 + x + 1
+ * = x^13 + x^11 + x^9 + x^8 + x^6 + x^5 + x^4 + x^3 + 1 = y
+ * y modulo (x^8 + x^4 + x^3 + x + 1)
+ * = x^7 + x^6 + 1.
+ *
+ * The modular reduction by m(x) guarantees the result will be a binary
+ * polynomial of less than degree 8, so that it can fit in a byte.
+ *
+ * The operation to multiply a binary polynomial b with x (the polynomial
+ * x in binary representation is 00000010) is:
+ *
+ * b_7x^8 + b_6x^7 + b_5x^6 + b_4x^5 + b_3x^4 + b_2x^3 + b_1x^2 + b_0x^1
+ *
+ * To get GF(b, x) we must reduce that by m(x). If b_7 is 0 (that is the
+ * most significant bit is 0 in b) then the result is already reduced. If
+ * it is 1, then we can reduce it by subtracting m(x) via an XOR.
+ *
+ * It follows that multiplication by x (00000010 or 0x02) can be implemented
+ * by performing a left shift followed by a conditional bitwise XOR with
+ * 0x1b. This operation on bytes is denoted by xtime(). Multiplication by
+ * higher powers of x can be implemented by repeated application of xtime().
+ *
+ * By adding intermediate results, multiplication by any constant can be
+ * implemented. For instance:
+ *
+ * GF(0x57, 0x13) = 0xfe because:
+ *
+ * xtime(b) = (b & 128) ? (b << 1 ^ 0x11b) : (b << 1)
+ *
+ * Note: We XOR with 0x11b instead of 0x1b because in javascript our
+ * datatype for b can be larger than 1 byte, so a left shift will not
+ * automatically eliminate bits that overflow a byte ... by XOR'ing the
+ * overflow bit with 1 (the extra one from 0x11b) we zero it out.
+ *
+ * GF(0x57, 0x02) = xtime(0x57) = 0xae
+ * GF(0x57, 0x04) = xtime(0xae) = 0x47
+ * GF(0x57, 0x08) = xtime(0x47) = 0x8e
+ * GF(0x57, 0x10) = xtime(0x8e) = 0x07
+ *
+ * GF(0x57, 0x13) = GF(0x57, (0x01 ^ 0x02 ^ 0x10))
+ *
+ * And by the distributive property (since XOR is addition and GF() is
+ * multiplication):
+ *
+ * = GF(0x57, 0x01) ^ GF(0x57, 0x02) ^ GF(0x57, 0x10)
+ * = 0x57 ^ 0xae ^ 0x07
+ * = 0xfe.
+ */
+function initialize() {
+ init = true;
+
+ /* Populate the Rcon table. These are the values given by
+ [x^(i-1),{00},{00},{00}] where x^(i-1) are powers of x (and x = 0x02)
+ in the field of GF(2^8), where i starts at 1.
+
+ rcon[0] = [0x00, 0x00, 0x00, 0x00]
+ rcon[1] = [0x01, 0x00, 0x00, 0x00] 2^(1-1) = 2^0 = 1
+ rcon[2] = [0x02, 0x00, 0x00, 0x00] 2^(2-1) = 2^1 = 2
+ ...
+ rcon[9] = [0x1B, 0x00, 0x00, 0x00] 2^(9-1) = 2^8 = 0x1B
+ rcon[10] = [0x36, 0x00, 0x00, 0x00] 2^(10-1) = 2^9 = 0x36
+
+ We only store the first byte because it is the only one used.
+ */
+ rcon = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36];
+
+ // compute xtime table which maps i onto GF(i, 0x02)
+ var xtime = new Array(256);
+ for(var i = 0; i < 128; ++i) {
+ xtime[i] = i << 1;
+ xtime[i + 128] = (i + 128) << 1 ^ 0x11B;
+ }
+
+ // compute all other tables
+ sbox = new Array(256);
+ isbox = new Array(256);
+ mix = new Array(4);
+ imix = new Array(4);
+ for(var i = 0; i < 4; ++i) {
+ mix[i] = new Array(256);
+ imix[i] = new Array(256);
+ }
+ var e = 0, ei = 0, e2, e4, e8, sx, sx2, me, ime;
+ for(var i = 0; i < 256; ++i) {
+ /* We need to generate the SubBytes() sbox and isbox tables so that
+ we can perform byte substitutions. This requires us to traverse
+ all of the elements in GF, find their multiplicative inverses,
+ and apply to each the following affine transformation:
+
+ bi' = bi ^ b(i + 4) mod 8 ^ b(i + 5) mod 8 ^ b(i + 6) mod 8 ^
+ b(i + 7) mod 8 ^ ci
+ for 0 <= i < 8, where bi is the ith bit of the byte, and ci is the
+ ith bit of a byte c with the value {63} or {01100011}.
+
+ It is possible to traverse every possible value in a Galois field
+ using what is referred to as a 'generator'. There are many
+ generators (128 out of 256): 3,5,6,9,11,82 to name a few. To fully
+ traverse GF we iterate 255 times, multiplying by our generator
+ each time.
+
+ On each iteration we can determine the multiplicative inverse for
+ the current element.
+
+ Suppose there is an element in GF 'e'. For a given generator 'g',
+ e = g^x. The multiplicative inverse of e is g^(255 - x). It turns
+ out that if use the inverse of a generator as another generator
+ it will produce all of the corresponding multiplicative inverses
+ at the same time. For this reason, we choose 5 as our inverse
+ generator because it only requires 2 multiplies and 1 add and its
+ inverse, 82, requires relatively few operations as well.
+
+ In order to apply the affine transformation, the multiplicative
+ inverse 'ei' of 'e' can be repeatedly XOR'd (4 times) with a
+ bit-cycling of 'ei'. To do this 'ei' is first stored in 's' and
+ 'x'. Then 's' is left shifted and the high bit of 's' is made the
+ low bit. The resulting value is stored in 's'. Then 'x' is XOR'd
+ with 's' and stored in 'x'. On each subsequent iteration the same
+ operation is performed. When 4 iterations are complete, 'x' is
+ XOR'd with 'c' (0x63) and the transformed value is stored in 'x'.
+ For example:
+
+ s = 01000001
+ x = 01000001
+
+ iteration 1: s = 10000010, x ^= s
+ iteration 2: s = 00000101, x ^= s
+ iteration 3: s = 00001010, x ^= s
+ iteration 4: s = 00010100, x ^= s
+ x ^= 0x63
+
+ This can be done with a loop where s = (s << 1) | (s >> 7). However,
+ it can also be done by using a single 16-bit (in this case 32-bit)
+ number 'sx'. Since XOR is an associative operation, we can set 'sx'
+ to 'ei' and then XOR it with 'sx' left-shifted 1,2,3, and 4 times.
+ The most significant bits will flow into the high 8 bit positions
+ and be correctly XOR'd with one another. All that remains will be
+ to cycle the high 8 bits by XOR'ing them all with the lower 8 bits
+ afterwards.
+
+ At the same time we're populating sbox and isbox we can precompute
+ the multiplication we'll need to do to do MixColumns() later.
+ */
+
+ // apply affine transformation
+ sx = ei ^ (ei << 1) ^ (ei << 2) ^ (ei << 3) ^ (ei << 4);
+ sx = (sx >> 8) ^ (sx & 255) ^ 0x63;
+
+ // update tables
+ sbox[e] = sx;
+ isbox[sx] = e;
+
+ /* Mixing columns is done using matrix multiplication. The columns
+ that are to be mixed are each a single word in the current state.
+ The state has Nb columns (4 columns). Therefore each column is a
+ 4 byte word. So to mix the columns in a single column 'c' where
+ its rows are r0, r1, r2, and r3, we use the following matrix
+ multiplication:
+
+ [2 3 1 1]*[r0,c]=[r'0,c]
+ [1 2 3 1] [r1,c] [r'1,c]
+ [1 1 2 3] [r2,c] [r'2,c]
+ [3 1 1 2] [r3,c] [r'3,c]
+
+ r0, r1, r2, and r3 are each 1 byte of one of the words in the
+ state (a column). To do matrix multiplication for each mixed
+ column c' we multiply the corresponding row from the left matrix
+ with the corresponding column from the right matrix. In total, we
+ get 4 equations:
+
+ r0,c' = 2*r0,c + 3*r1,c + 1*r2,c + 1*r3,c
+ r1,c' = 1*r0,c + 2*r1,c + 3*r2,c + 1*r3,c
+ r2,c' = 1*r0,c + 1*r1,c + 2*r2,c + 3*r3,c
+ r3,c' = 3*r0,c + 1*r1,c + 1*r2,c + 2*r3,c
+
+ As usual, the multiplication is as previously defined and the
+ addition is XOR. In order to optimize mixing columns we can store
+ the multiplication results in tables. If you think of the whole
+ column as a word (it might help to visualize by mentally rotating
+ the equations above by counterclockwise 90 degrees) then you can
+ see that it would be useful to map the multiplications performed on
+ each byte (r0, r1, r2, r3) onto a word as well. For instance, we
+ could map 2*r0,1*r0,1*r0,3*r0 onto a word by storing 2*r0 in the
+ highest 8 bits and 3*r0 in the lowest 8 bits (with the other two
+ respectively in the middle). This means that a table can be
+ constructed that uses r0 as an index to the word. We can do the
+ same with r1, r2, and r3, creating a total of 4 tables.
+
+ To construct a full c', we can just look up each byte of c in
+ their respective tables and XOR the results together.
+
+ Also, to build each table we only have to calculate the word
+ for 2,1,1,3 for every byte ... which we can do on each iteration
+ of this loop since we will iterate over every byte. After we have
+ calculated 2,1,1,3 we can get the results for the other tables
+ by cycling the byte at the end to the beginning. For instance
+ we can take the result of table 2,1,1,3 and produce table 3,2,1,1
+ by moving the right most byte to the left most position just like
+ how you can imagine the 3 moved out of 2,1,1,3 and to the front
+ to produce 3,2,1,1.
+
+ There is another optimization in that the same multiples of
+ the current element we need in order to advance our generator
+ to the next iteration can be reused in performing the 2,1,1,3
+ calculation. We also calculate the inverse mix column tables,
+ with e,9,d,b being the inverse of 2,1,1,3.
+
+ When we're done, and we need to actually mix columns, the first
+ byte of each state word should be put through mix[0] (2,1,1,3),
+ the second through mix[1] (3,2,1,1) and so forth. Then they should
+ be XOR'd together to produce the fully mixed column.
+ */
+
+ // calculate mix and imix table values
+ sx2 = xtime[sx];
+ e2 = xtime[e];
+ e4 = xtime[e2];
+ e8 = xtime[e4];
+ me =
+ (sx2 << 24) ^ // 2
+ (sx << 16) ^ // 1
+ (sx << 8) ^ // 1
+ (sx ^ sx2); // 3
+ ime =
+ (e2 ^ e4 ^ e8) << 24 ^ // E (14)
+ (e ^ e8) << 16 ^ // 9
+ (e ^ e4 ^ e8) << 8 ^ // D (13)
+ (e ^ e2 ^ e8); // B (11)
+ // produce each of the mix tables by rotating the 2,1,1,3 value
+ for(var n = 0; n < 4; ++n) {
+ mix[n][e] = me;
+ imix[n][sx] = ime;
+ // cycle the right most byte to the left most position
+ // ie: 2,1,1,3 becomes 3,2,1,1
+ me = me << 24 | me >>> 8;
+ ime = ime << 24 | ime >>> 8;
+ }
+
+ // get next element and inverse
+ if(e === 0) {
+ // 1 is the inverse of 1
+ e = ei = 1;
+ } else {
+ // e = 2e + 2*2*2*(10e)) = multiply e by 82 (chosen generator)
+ // ei = ei + 2*2*ei = multiply ei by 5 (inverse generator)
+ e = e2 ^ xtime[xtime[xtime[e2 ^ e8]]];
+ ei ^= xtime[xtime[ei]];
+ }
+ }
+}
+
+/**
+ * Generates a key schedule using the AES key expansion algorithm.
+ *
+ * The AES algorithm takes the Cipher Key, K, and performs a Key Expansion
+ * routine to generate a key schedule. The Key Expansion generates a total
+ * of Nb*(Nr + 1) words: the algorithm requires an initial set of Nb words,
+ * and each of the Nr rounds requires Nb words of key data. The resulting
+ * key schedule consists of a linear array of 4-byte words, denoted [wi ],
+ * with i in the range 0 ≤ i < Nb(Nr + 1).
+ *
+ * KeyExpansion(byte key[4*Nk], word w[Nb*(Nr+1)], Nk)
+ * AES-128 (Nb=4, Nk=4, Nr=10)
+ * AES-192 (Nb=4, Nk=6, Nr=12)
+ * AES-256 (Nb=4, Nk=8, Nr=14)
+ * Note: Nr=Nk+6.
+ *
+ * Nb is the number of columns (32-bit words) comprising the State (or
+ * number of bytes in a block). For AES, Nb=4.
+ *
+ * @param key the key to schedule (as an array of 32-bit words).
+ * @param decrypt true to modify the key schedule to decrypt, false not to.
+ *
+ * @return the generated key schedule.
+ */
+function _expandKey(key, decrypt) {
+ // copy the key's words to initialize the key schedule
+ var w = key.slice(0);
+
+ /* RotWord() will rotate a word, moving the first byte to the last
+ byte's position (shifting the other bytes left).
+
+ We will be getting the value of Rcon at i / Nk. 'i' will iterate
+ from Nk to (Nb * Nr+1). Nk = 4 (4 byte key), Nb = 4 (4 words in
+ a block), Nr = Nk + 6 (10). Therefore 'i' will iterate from
+ 4 to 44 (exclusive). Each time we iterate 4 times, i / Nk will
+ increase by 1. We use a counter iNk to keep track of this.
+ */
+
+ // go through the rounds expanding the key
+ var temp, iNk = 1;
+ var Nk = w.length;
+ var Nr1 = Nk + 6 + 1;
+ var end = Nb * Nr1;
+ for(var i = Nk; i < end; ++i) {
+ temp = w[i - 1];
+ if(i % Nk === 0) {
+ // temp = SubWord(RotWord(temp)) ^ Rcon[i / Nk]
+ temp =
+ sbox[temp >>> 16 & 255] << 24 ^
+ sbox[temp >>> 8 & 255] << 16 ^
+ sbox[temp & 255] << 8 ^
+ sbox[temp >>> 24] ^ (rcon[iNk] << 24);
+ iNk++;
+ } else if(Nk > 6 && (i % Nk === 4)) {
+ // temp = SubWord(temp)
+ temp =
+ sbox[temp >>> 24] << 24 ^
+ sbox[temp >>> 16 & 255] << 16 ^
+ sbox[temp >>> 8 & 255] << 8 ^
+ sbox[temp & 255];
+ }
+ w[i] = w[i - Nk] ^ temp;
+ }
+
+ /* When we are updating a cipher block we always use the code path for
+ encryption whether we are decrypting or not (to shorten code and
+ simplify the generation of look up tables). However, because there
+ are differences in the decryption algorithm, other than just swapping
+ in different look up tables, we must transform our key schedule to
+ account for these changes:
+
+ 1. The decryption algorithm gets its key rounds in reverse order.
+ 2. The decryption algorithm adds the round key before mixing columns
+ instead of afterwards.
+
+ We don't need to modify our key schedule to handle the first case,
+ we can just traverse the key schedule in reverse order when decrypting.
+
+ The second case requires a little work.
+
+ The tables we built for performing rounds will take an input and then
+ perform SubBytes() and MixColumns() or, for the decrypt version,
+ InvSubBytes() and InvMixColumns(). But the decrypt algorithm requires
+ us to AddRoundKey() before InvMixColumns(). This means we'll need to
+ apply some transformations to the round key to inverse-mix its columns
+ so they'll be correct for moving AddRoundKey() to after the state has
+ had its columns inverse-mixed.
+
+ To inverse-mix the columns of the state when we're decrypting we use a
+ lookup table that will apply InvSubBytes() and InvMixColumns() at the
+ same time. However, the round key's bytes are not inverse-substituted
+ in the decryption algorithm. To get around this problem, we can first
+ substitute the bytes in the round key so that when we apply the
+ transformation via the InvSubBytes()+InvMixColumns() table, it will
+ undo our substitution leaving us with the original value that we
+ want -- and then inverse-mix that value.
+
+ This change will correctly alter our key schedule so that we can XOR
+ each round key with our already transformed decryption state. This
+ allows us to use the same code path as the encryption algorithm.
+
+ We make one more change to the decryption key. Since the decryption
+ algorithm runs in reverse from the encryption algorithm, we reverse
+ the order of the round keys to avoid having to iterate over the key
+ schedule backwards when running the encryption algorithm later in
+ decryption mode. In addition to reversing the order of the round keys,
+ we also swap each round key's 2nd and 4th rows. See the comments
+ section where rounds are performed for more details about why this is
+ done. These changes are done inline with the other substitution
+ described above.
+ */
+ if(decrypt) {
+ var tmp;
+ var m0 = imix[0];
+ var m1 = imix[1];
+ var m2 = imix[2];
+ var m3 = imix[3];
+ var wnew = w.slice(0);
+ end = w.length;
+ for(var i = 0, wi = end - Nb; i < end; i += Nb, wi -= Nb) {
+ // do not sub the first or last round key (round keys are Nb
+ // words) as no column mixing is performed before they are added,
+ // but do change the key order
+ if(i === 0 || i === (end - Nb)) {
+ wnew[i] = w[wi];
+ wnew[i + 1] = w[wi + 3];
+ wnew[i + 2] = w[wi + 2];
+ wnew[i + 3] = w[wi + 1];
+ } else {
+ // substitute each round key byte because the inverse-mix
+ // table will inverse-substitute it (effectively cancel the
+ // substitution because round key bytes aren't sub'd in
+ // decryption mode) and swap indexes 3 and 1
+ for(var n = 0; n < Nb; ++n) {
+ tmp = w[wi + n];
+ wnew[i + (3&-n)] =
+ m0[sbox[tmp >>> 24]] ^
+ m1[sbox[tmp >>> 16 & 255]] ^
+ m2[sbox[tmp >>> 8 & 255]] ^
+ m3[sbox[tmp & 255]];
+ }
+ }
+ }
+ w = wnew;
+ }
+
+ return w;
+}
+
+/**
+ * Updates a single block (16 bytes) using AES. The update will either
+ * encrypt or decrypt the block.
+ *
+ * @param w the key schedule.
+ * @param input the input block (an array of 32-bit words).
+ * @param output the updated output block.
+ * @param decrypt true to decrypt the block, false to encrypt it.
+ */
+function _updateBlock(w, input, output, decrypt) {
+ /*
+ Cipher(byte in[4*Nb], byte out[4*Nb], word w[Nb*(Nr+1)])
+ begin
+ byte state[4,Nb]
+ state = in
+ AddRoundKey(state, w[0, Nb-1])
+ for round = 1 step 1 to Nr–1
+ SubBytes(state)
+ ShiftRows(state)
+ MixColumns(state)
+ AddRoundKey(state, w[round*Nb, (round+1)*Nb-1])
+ end for
+ SubBytes(state)
+ ShiftRows(state)
+ AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1])
+ out = state
+ end
+
+ InvCipher(byte in[4*Nb], byte out[4*Nb], word w[Nb*(Nr+1)])
+ begin
+ byte state[4,Nb]
+ state = in
+ AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1])
+ for round = Nr-1 step -1 downto 1
+ InvShiftRows(state)
+ InvSubBytes(state)
+ AddRoundKey(state, w[round*Nb, (round+1)*Nb-1])
+ InvMixColumns(state)
+ end for
+ InvShiftRows(state)
+ InvSubBytes(state)
+ AddRoundKey(state, w[0, Nb-1])
+ out = state
+ end
+ */
+
+ // Encrypt: AddRoundKey(state, w[0, Nb-1])
+ // Decrypt: AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1])
+ var Nr = w.length / 4 - 1;
+ var m0, m1, m2, m3, sub;
+ if(decrypt) {
+ m0 = imix[0];
+ m1 = imix[1];
+ m2 = imix[2];
+ m3 = imix[3];
+ sub = isbox;
+ } else {
+ m0 = mix[0];
+ m1 = mix[1];
+ m2 = mix[2];
+ m3 = mix[3];
+ sub = sbox;
+ }
+ var a, b, c, d, a2, b2, c2;
+ a = input[0] ^ w[0];
+ b = input[decrypt ? 3 : 1] ^ w[1];
+ c = input[2] ^ w[2];
+ d = input[decrypt ? 1 : 3] ^ w[3];
+ var i = 3;
+
+ /* In order to share code we follow the encryption algorithm when both
+ encrypting and decrypting. To account for the changes required in the
+ decryption algorithm, we use different lookup tables when decrypting
+ and use a modified key schedule to account for the difference in the
+ order of transformations applied when performing rounds. We also get
+ key rounds in reverse order (relative to encryption). */
+ for(var round = 1; round < Nr; ++round) {
+ /* As described above, we'll be using table lookups to perform the
+ column mixing. Each column is stored as a word in the state (the
+ array 'input' has one column as a word at each index). In order to
+ mix a column, we perform these transformations on each row in c,
+ which is 1 byte in each word. The new column for c0 is c'0:
+
+ m0 m1 m2 m3
+ r0,c'0 = 2*r0,c0 + 3*r1,c0 + 1*r2,c0 + 1*r3,c0
+ r1,c'0 = 1*r0,c0 + 2*r1,c0 + 3*r2,c0 + 1*r3,c0
+ r2,c'0 = 1*r0,c0 + 1*r1,c0 + 2*r2,c0 + 3*r3,c0
+ r3,c'0 = 3*r0,c0 + 1*r1,c0 + 1*r2,c0 + 2*r3,c0
+
+ So using mix tables where c0 is a word with r0 being its upper
+ 8 bits and r3 being its lower 8 bits:
+
+ m0[c0 >> 24] will yield this word: [2*r0,1*r0,1*r0,3*r0]
+ ...
+ m3[c0 & 255] will yield this word: [1*r3,1*r3,3*r3,2*r3]
+
+ Therefore to mix the columns in each word in the state we
+ do the following (& 255 omitted for brevity):
+ c'0,r0 = m0[c0 >> 24] ^ m1[c1 >> 16] ^ m2[c2 >> 8] ^ m3[c3]
+ c'0,r1 = m0[c0 >> 24] ^ m1[c1 >> 16] ^ m2[c2 >> 8] ^ m3[c3]
+ c'0,r2 = m0[c0 >> 24] ^ m1[c1 >> 16] ^ m2[c2 >> 8] ^ m3[c3]
+ c'0,r3 = m0[c0 >> 24] ^ m1[c1 >> 16] ^ m2[c2 >> 8] ^ m3[c3]
+
+ However, before mixing, the algorithm requires us to perform
+ ShiftRows(). The ShiftRows() transformation cyclically shifts the
+ last 3 rows of the state over different offsets. The first row
+ (r = 0) is not shifted.
+
+ s'_r,c = s_r,(c + shift(r, Nb) mod Nb
+ for 0 < r < 4 and 0 <= c < Nb and
+ shift(1, 4) = 1
+ shift(2, 4) = 2
+ shift(3, 4) = 3.
+
+ This causes the first byte in r = 1 to be moved to the end of
+ the row, the first 2 bytes in r = 2 to be moved to the end of
+ the row, the first 3 bytes in r = 3 to be moved to the end of
+ the row:
+
+ r1: [c0 c1 c2 c3] => [c1 c2 c3 c0]
+ r2: [c0 c1 c2 c3] [c2 c3 c0 c1]
+ r3: [c0 c1 c2 c3] [c3 c0 c1 c2]
+
+ We can make these substitutions inline with our column mixing to
+ generate an updated set of equations to produce each word in the
+ state (note the columns have changed positions):
+
+ c0 c1 c2 c3 => c0 c1 c2 c3
+ c0 c1 c2 c3 c1 c2 c3 c0 (cycled 1 byte)
+ c0 c1 c2 c3 c2 c3 c0 c1 (cycled 2 bytes)
+ c0 c1 c2 c3 c3 c0 c1 c2 (cycled 3 bytes)
+
+ Therefore:
+
+ c'0 = 2*r0,c0 + 3*r1,c1 + 1*r2,c2 + 1*r3,c3
+ c'0 = 1*r0,c0 + 2*r1,c1 + 3*r2,c2 + 1*r3,c3
+ c'0 = 1*r0,c0 + 1*r1,c1 + 2*r2,c2 + 3*r3,c3
+ c'0 = 3*r0,c0 + 1*r1,c1 + 1*r2,c2 + 2*r3,c3
+
+ c'1 = 2*r0,c1 + 3*r1,c2 + 1*r2,c3 + 1*r3,c0
+ c'1 = 1*r0,c1 + 2*r1,c2 + 3*r2,c3 + 1*r3,c0
+ c'1 = 1*r0,c1 + 1*r1,c2 + 2*r2,c3 + 3*r3,c0
+ c'1 = 3*r0,c1 + 1*r1,c2 + 1*r2,c3 + 2*r3,c0
+
+ ... and so forth for c'2 and c'3. The important distinction is
+ that the columns are cycling, with c0 being used with the m0
+ map when calculating c0, but c1 being used with the m0 map when
+ calculating c1 ... and so forth.
+
+ When performing the inverse we transform the mirror image and
+ skip the bottom row, instead of the top one, and move upwards:
+
+ c3 c2 c1 c0 => c0 c3 c2 c1 (cycled 3 bytes) *same as encryption
+ c3 c2 c1 c0 c1 c0 c3 c2 (cycled 2 bytes)
+ c3 c2 c1 c0 c2 c1 c0 c3 (cycled 1 byte) *same as encryption
+ c3 c2 c1 c0 c3 c2 c1 c0
+
+ If you compare the resulting matrices for ShiftRows()+MixColumns()
+ and for InvShiftRows()+InvMixColumns() the 2nd and 4th columns are
+ different (in encrypt mode vs. decrypt mode). So in order to use
+ the same code to handle both encryption and decryption, we will
+ need to do some mapping.
+
+ If in encryption mode we let a=c0, b=c1, c=c2, d=c3, and r be
+ a row number in the state, then the resulting matrix in encryption
+ mode for applying the above transformations would be:
+
+ r1: a b c d
+ r2: b c d a
+ r3: c d a b
+ r4: d a b c
+
+ If we did the same in decryption mode we would get:
+
+ r1: a d c b
+ r2: b a d c
+ r3: c b a d
+ r4: d c b a
+
+ If instead we swap d and b (set b=c3 and d=c1), then we get:
+
+ r1: a b c d
+ r2: d a b c
+ r3: c d a b
+ r4: b c d a
+
+ Now the 1st and 3rd rows are the same as the encryption matrix. All
+ we need to do then to make the mapping exactly the same is to swap
+ the 2nd and 4th rows when in decryption mode. To do this without
+ having to do it on each iteration, we swapped the 2nd and 4th rows
+ in the decryption key schedule. We also have to do the swap above
+ when we first pull in the input and when we set the final output. */
+ a2 =
+ m0[a >>> 24] ^
+ m1[b >>> 16 & 255] ^
+ m2[c >>> 8 & 255] ^
+ m3[d & 255] ^ w[++i];
+ b2 =
+ m0[b >>> 24] ^
+ m1[c >>> 16 & 255] ^
+ m2[d >>> 8 & 255] ^
+ m3[a & 255] ^ w[++i];
+ c2 =
+ m0[c >>> 24] ^
+ m1[d >>> 16 & 255] ^
+ m2[a >>> 8 & 255] ^
+ m3[b & 255] ^ w[++i];
+ d =
+ m0[d >>> 24] ^
+ m1[a >>> 16 & 255] ^
+ m2[b >>> 8 & 255] ^
+ m3[c & 255] ^ w[++i];
+ a = a2;
+ b = b2;
+ c = c2;
+ }
+
+ /*
+ Encrypt:
+ SubBytes(state)
+ ShiftRows(state)
+ AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1])
+
+ Decrypt:
+ InvShiftRows(state)
+ InvSubBytes(state)
+ AddRoundKey(state, w[0, Nb-1])
+ */
+ // Note: rows are shifted inline
+ output[0] =
+ (sub[a >>> 24] << 24) ^
+ (sub[b >>> 16 & 255] << 16) ^
+ (sub[c >>> 8 & 255] << 8) ^
+ (sub[d & 255]) ^ w[++i];
+ output[decrypt ? 3 : 1] =
+ (sub[b >>> 24] << 24) ^
+ (sub[c >>> 16 & 255] << 16) ^
+ (sub[d >>> 8 & 255] << 8) ^
+ (sub[a & 255]) ^ w[++i];
+ output[2] =
+ (sub[c >>> 24] << 24) ^
+ (sub[d >>> 16 & 255] << 16) ^
+ (sub[a >>> 8 & 255] << 8) ^
+ (sub[b & 255]) ^ w[++i];
+ output[decrypt ? 1 : 3] =
+ (sub[d >>> 24] << 24) ^
+ (sub[a >>> 16 & 255] << 16) ^
+ (sub[b >>> 8 & 255] << 8) ^
+ (sub[c & 255]) ^ w[++i];
+}
+
+/**
+ * Deprecated. Instead, use:
+ *
+ * forge.cipher.createCipher('AES-', key);
+ * forge.cipher.createDecipher('AES-', key);
+ *
+ * Creates a deprecated AES cipher object. This object's mode will default to
+ * CBC (cipher-block-chaining).
+ *
+ * The key and iv may be given as a string of bytes, an array of bytes, a
+ * byte buffer, or an array of 32-bit words.
+ *
+ * @param options the options to use.
+ * key the symmetric key to use.
+ * output the buffer to write to.
+ * decrypt true for decryption, false for encryption.
+ * mode the cipher mode to use (default: 'CBC').
+ *
+ * @return the cipher.
+ */
+function _createCipher(options) {
+ options = options || {};
+ var mode = (options.mode || 'CBC').toUpperCase();
+ var algorithm = 'AES-' + mode;
+
+ var cipher;
+ if(options.decrypt) {
+ cipher = forge.cipher.createDecipher(algorithm, options.key);
+ } else {
+ cipher = forge.cipher.createCipher(algorithm, options.key);
+ }
+
+ // backwards compatible start API
+ var start = cipher.start;
+ cipher.start = function(iv, options) {
+ // backwards compatibility: support second arg as output buffer
+ var output = null;
+ if(options instanceof forge.util.ByteBuffer) {
+ output = options;
+ options = {};
+ }
+ options = options || {};
+ options.output = output;
+ options.iv = iv;
+ start.call(cipher, options);
+ };
+
+ return cipher;
+}
+
+} // end module implementation
+
+/* ########## Begin module wrapper ########## */
+var name = 'aes';
+if(typeof define !== 'function') {
+ // NodeJS -> AMD
+ if(typeof module === 'object' && module.exports) {
+ var nodeJS = true;
+ define = function(ids, factory) {
+ factory(require, module);
+ };
+ } else {
+ //
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MeshCommander
+
+
+ LMS MeshCommander
+
+
+
+ ScriptCommander
+
+
+
+ Intel® Active Management Technology
+
+
+ Intel® System Defense Utility
+
+
+ Intel® Manageability Commander
+
+
+ Intel® Unite - Hardware Management
+
+
+
+
+
+
+
+
+
+
+
+ Disconnected
+
+
+ Loading...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
No known computers
+
+
Get started by
adding computers or drag & dropping
a computer list file in this window.
+
+
+
+
+
+
+
+
+
+
No known computers
+
+
Get started by
adding computers or drag & dropping
a computer list file in this window.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Intel® AMT USB Setup.bin Manager
+
Get started by
creating a new file,
opening an existing one
or drag & dropping a setup.bin file in this window.
+
+
+
+
+
+
+
+
Intel® AMT USB Setup.bin Manager
+
Get started by
creating a new file,
opening an existing one
or drag & dropping a setup.bin file in this window.
+
+
+
+
+
+
+
+
+
+
+
+
+
Certificate Manager
+
Certificates play an important role in all sorts of Intel® AMT security tasks: TLS network authentication, CIRA configuration, audit log signing and more. Use this panel to create and manage your console certificate.
+
+
+
+
+
+
+
+
+
+
+
Certificate Manager
+
Certificates play an important role in all sorts of Intel® AMT security tasks: TLS network authentication, CIRA configuration, audit log signing and more. Use this panel to create and manage your console certificate.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Floppy, blocks are 512 bytes.
+
+
+
+
CDROM, blocks are 2048 bytes.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Loading...
+
+
+
System Status
+
+
+
+
+
Hardware Information
+
+
+
+
+
+
Event Log
+
+
+
+
+
+
+
Network Settings
+
+
+
+
+
+
+
+
User Accounts
+
+
+
+
+
+
+
+
Serial-over-LAN Terminal
+
+
+
Intel® AMT Redirection port or Serial-over-LAN feature is disabled, click here to enable it.
+
+
+
+
Remote computer is not powered on, click here to issue a power command.
+
+
+
+
+
+
+
+
+
+
Intel® AMT Redirection port or KVM feature is disabled, click here to enable it.
+
+
+
+
Remote computer is not powered on, click here to issue a power command.
+
+
+
+
+
+
+
+
+
Audit Log
+
+
+
+
+
+
Security Settings
+
+
+
+
+
+
Internet Settings
+
+
+
+
+
+
System Defense
+
+
+
+
+
+
Agent Presence
+
+
+
+
+
+
Script Editor
+
+
+
+
Script
+
+
+
Compiled Script
+
+
+
+
Variables
+
+
+
Console
+
+
+
+
+
+
Storage
+
+
+
+
+
+
Event Subscriptions
+
+
+
+
+
+
Wake Alarms
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Local Network Any Permission
+
Granted Permissions
+
+
+
*Minimum 8 characters with upper, lowercase, 0-9, and one of !@#$%^&*()+-
+
+
+
+
+
+
+
+
+
+
+
+
*Minimum 8 characters with upper, lowercase, 0-9, and one of !@#$%^&*()+-
+
+
+
+
+
+
+
+
+
Digest / None Digest / TLS Kerberos / None Kerberos / TLS Auth / Security
+
+
+
+
*Minimum 8 characters with upper, lowercase, 0-9, and one of !@#$%^&*()+-
+
+
+
+
*Alternate hostname for Kerberos token request
+
+
+
+
+
+
+
+ Warning: Some power actions may result in data loss and may disconnect the desktop, terminal or disk redirection sessions.
+
+
+
+
+
+
Primary display Secondary display Third display Consent Display
+
+
+
+
+
+
+ RLE8, Color Fast
+ RLE16, Color
+ RLE4G, Gray Fastest
+ RLE8G, Gray Fast
+ RAW8, Color Slow
+ RAW16, Color Very Slow
+
+
Image Encoding
+
+
+
+
+
Software KVM
+
+
+ 50%
+ 40%
+ 30%
+ 20%
+ 10%
+ 5%
+ 1%
+
+
Quality
+
+
+
+ 100%
+ 87.5%
+ 75%
+ 62.5%
+ 50%
+ 37.5%
+ 25%
+ 12.5%
+
+
Scaling
+
+
+
+
+
+
+
+
+
+ Redirection Port
+ KVM Remote Desktop
+ IDE-Redirection
+ Serial-over-LAN
+
+
+ Not Required
+ Required for KVM only
+ Always Required
+
+
+
+
+
+
+
+
+
+
+
+ WPA2 PSK
+
+ WPA PSK
+
+
+
+
Authentication
+
+
+
+ CCMP-AES
+ TKIP-RC4
+ WEP
+ None
+
+
Encryption
+
+
+
+
+
+
+
+ Valid Record
+ Scrambled Record
+
+
+
+
+ Version 1
+ Version 2
+ Version 3
+ Version 4
+
+
Setup.bin version
+
+
+
+ Records will not be consumed
+ Records will be consumed
+
+
Record consumption
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Use encryption. The file will contain Intel® AMT credentials, saving using a password may help protect this data.
+
+
+
+
+
*Minimum 8 characters with upper, lowercase, 0-9, and one of !@#$%^&*()+-
+
+
+
+
+
+
+ This will save the entire state of Intel® AMT for this machine into file. Passwords will not be saved, but some sensitive data may be included.
+
+
+
+
+
+ Disabled
+ ICMP response
+ RMCP response
+ ICMP & RMCP response
+
+
+
+
+
+
+ Disabled
+ Disabled, DHCP update
+ Enabled
+
+
Dynamic DNS client
+
+
+
+
Defaut Interval is 1440 minutes, Default TTL is 900 seconds.
+
+
+
+
+
+
+
+ Power up
+ Power cycle
+ Power down
+ Reset
+ OS Wake from Standby
+ OS Power Saving
+ Set boot options
+
+
Remote Command
+
+
+
+
+ None
+ Force CD/DVD Boot
+ Force PXE Boot
+ Force Hard Disk Boot
+ Force Diagnostic Boot
+
+
Boot Source
+
+
+
+ None
+ Index 1
+ Index 2
+ Index 3
+ Index 4
+
+
Boot Media Index
+
+
+
+ Boot to floppy
+ Boot to CDROM
+
+
IDER Boot Device
+
+
+
+ System Default
+ Quiet
+ Verbose
+ Blank Screen
+
+
Verbocity
+
+
+
+
WARNING: TLS is not used, password will be sent in the clear.
+
+
+
+
+
+
+
+
+
+
+
+
Wake date (year-month-day)
+
+
+
+
+
+
Wake time (hour:min:sec)
+
+
+
+
+
+
Interval (days-hours-min)
+
+
+
+
+ Keep alarm
+ Delete on completion
+
+
+
After wake
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mesh256.png b/mesh256.png
new file mode 100644
index 0000000..7b91526
Binary files /dev/null and b/mesh256.png differ
diff --git a/mesh256s.png b/mesh256s.png
new file mode 100644
index 0000000..fafd359
Binary files /dev/null and b/mesh256s.png differ
diff --git a/mesh32s.png b/mesh32s.png
new file mode 100644
index 0000000..31bac9c
Binary files /dev/null and b/mesh32s.png differ
diff --git a/meshcentral-server-0.2.0.js b/meshcentral-server-0.2.0.js
new file mode 100644
index 0000000..d07d321
--- /dev/null
+++ b/meshcentral-server-0.2.0.js
@@ -0,0 +1,286 @@
+/**
+* @description MeshCentral2 communication using websocket
+* @author Ylian Saint-Hilaire
+* @version v0.2.0a
+*/
+
+// Construct a MeshCentral2 communication object
+var CreateMeshCentralServer = function (host, port, path, username, password, token, certhash) {
+ var obj = {};
+ obj.host = host;
+ obj.port = port;
+ obj.path = path;
+ obj.username = username;
+ obj.password = password;
+ obj.token = token;
+ obj.certhash = certhash;
+ //obj.proxy = proxy;
+ //obj.proxyPort = 80;
+ obj.socket = null;
+ obj.socketState = 0;
+ obj.net = require('net');
+ obj.tls = require('tls');
+ obj.crypto = require('crypto');
+ obj.constants = require('constants');
+ obj.xtlsoptions = null;
+ obj.accumulator = "";
+ obj.accopcodes = 0;
+ obj.acclen = -1;
+ obj.accmask = false;
+ obj.meshes = {};
+ obj.computerlist = [];
+ obj.userinfo = null;
+ obj.xtlsCertificate = null;
+ obj.xtlsFingerprint = null;
+ obj.meshServerConnect = true;
+
+ // Events
+ obj.onStateChange = null;
+ obj.onNodeChange = null;
+
+ /*
+ // Parse the proxy
+ if (obj.proxy == '') { proxy = null; }
+ if (obj.proxy.indexOf(':') > 0) {
+ obj.proxyPort = parseInt(obj.proxy.substring(obj.proxy.indexOf(':') + 1));
+ obj.proxy = obj.proxy.substring(0, obj.proxy.indexOf(':'));
+ if (isNaN(obj.proxyPort)) { obj.proxy = null; obj.proxyPort = 0; }
+ }
+ */
+
+ // Called to initiate a websocket connection to the server
+ obj.connect = function () {
+ obj.socketState = 1;
+ if (obj.onStateChange != null) { obj.onStateChange(obj, obj.socketState); }
+ obj.accumulator = "";
+ obj.accopcodes = 0;
+ obj.acclen = -1;
+ obj.accmask = false;
+ obj.xtlsFingerprint = null;
+ if (obj.certhash == null) {
+ obj.socket = new obj.net.Socket();
+ obj.socket.setEncoding('binary');
+ obj.socket.connect(obj.port, obj.host, obj.xxOnSocketConnected);
+ } else {
+ //console.log('Connecting to wss://' + obj.host + ':' + obj.port + obj.path);
+ obj.socket = obj.tls.connect(obj.port, obj.host, { rejectUnauthorized: false }, _OnSocketConnected);
+ obj.socket.setEncoding('binary');
+ }
+ obj.socket.on('data', _OnSocketData);
+ obj.socket.on('close', _OnSocketClosed);
+ obj.socket.on('error', _OnSocketClosed);
+ }
+
+ obj.disconnect = function () { _OnSocketClosed("UserDisconnect"); }
+ obj.send = function (obj) { _Send(obj); }
+
+ // Called when the socket is connected, we still need to do work to get the websocket connected
+ function _OnSocketConnected() {
+ if (obj.socket == null) return;
+ // Check if this is really the MeshServer we want to connect to
+ obj.xtlsCertificate = obj.socket.getPeerCertificate();
+ obj.xtlsFingerprint = obj.xtlsCertificate.fingerprint.split(':').join('').toLowerCase();
+ if (obj.xtlsFingerprint != obj.certhash.split(':').join('').toLowerCase()) { _OnSocketClosed('HashMatchFail'); return; }
+
+ // If a authentication token is provided, place it in the login URL
+ var urlExtras = '';
+ if (obj.token != null) { urlExtras = '&token=' + obj.token; }
+
+ // Send the websocket switching header
+ obj.socket.write(new Buffer('GET ' + obj.path + '?user=' + encodeURIComponent(obj.username) + '&pass=' + encodeURIComponent(obj.password) + urlExtras + " HTTP/1.1\r\nHost: " + obj.host + "\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\n\r\n", "binary"));
+ }
+
+ // Called when socket data is received from the server
+ function _OnSocketData(e) {
+ obj.accumulator += e;
+ if (obj.socketState == 1) {
+ // Look for the HTTP header response
+ var i = obj.accumulator.indexOf('\r\n\r\n');
+ if (i >= 0) {
+ var header = parseHttpHeader(obj.accumulator.substring(0, i));
+ if ((header != null) && (header._Path == '101')) {
+ // Success
+ obj.accumulator = obj.accumulator.substring(i + 4);
+ obj.socketState = 2;
+ if (obj.onStateChange != null) { obj.onStateChange(obj, obj.socketState); }
+ //console.log('websocket connected');
+ } else {
+ // Fail
+ _OnSocketClosed();
+ }
+ }
+ }
+ if (obj.socketState >= 2) {
+ // Parse WebSocket data
+ //console.log('ACC(' + obj.accumulator.length + '):' + obj.accumulator);
+ while (_parseWsData() != 0) { }
+ }
+ };
+
+ // Parses websocket data from a socket connection, returns the number of bytes consumed.
+ function _parseWsData() {
+ if (obj.acclen == -1) {
+ // Look for a websocket header
+ if (obj.accumulator.length < 2) return 0;
+ var headsize = 2;
+ obj.accopcodes = obj.accumulator.charCodeAt(0);
+ obj.accmask = ((obj.accumulator.charCodeAt(1) & 0x80) != 0)
+ obj.acclen = (obj.accumulator.charCodeAt(1) & 0x7F);
+ if (obj.acclen == 126) {
+ if (obj.accumulator.length < 4) return 0;
+ headsize = 4;
+ obj.acclen = ReadShort(obj.accumulator, 2);
+ }
+ else if (obj.acclen == 127) {
+ if (obj.accumulator.length < 10) return 0;
+ headsize = 10;
+ obj.acclen = ReadInt(obj.accumulator, 6);
+ }
+ if (obj.accmask == true) {
+ // TODO: Do unmasking here.
+ headsize += 4;
+ }
+ //console.log('FIN: ' + ((obj.accopcodes & 0x80) != 0) + ', OP: ' + (obj.accopcodes & 0x0F) + ', LEN: ' + obj.acclen + ', MASK: ' + obj.accmask);
+ obj.accumulator = obj.accumulator.substring(headsize);
+ return headsize;
+ } else {
+ // Read the data
+ if (obj.accumulator.length < obj.acclen) return 0;
+ _OnWebSocketMessage(((obj.accopcodes & 0x80) != 0), (obj.accopcodes & 0x0F), obj.accumulator.substring(0, obj.acclen));
+ obj.accumulator = obj.accumulator.substring(obj.acclen);
+ var out = obj.acclen;
+ obj.acclen = -1;
+ return out;
+ }
+ }
+
+ // Called when the a command is received from the server
+ function _OnWebSocketMessage(fin, op, data) {
+ //console.log('FIN: ' + fin + ', OP: ' + op + ', LEN: ' + data.length, ': ' + data);
+ if (op == 8) { _OnSocketClosed('RemoteDisconnect'); return; } // Close the connection
+ if (op != 1) { return; } // We only process text frames
+
+ // Parse the incoming JSON command
+ var message = null;
+ try { message = JSON.parse(data); } catch (ex) { return; }
+ if (message == null) return;
+
+ // Process the command
+ switch (message.action) {
+ case 'close': {
+ _OnSocketClosed(message.cause, message.msg);
+ break;
+ }
+ case 'serverinfo': {
+ // We got server information, confirm good login.
+ obj.socketState = 3;
+ if (obj.onStateChange != null) { obj.onStateChange(obj, obj.socketState); }
+ _Send({ 'action': 'meshes' });
+ break;
+ }
+ case 'userinfo': {
+ obj.userinfo = message.userinfo;
+ break;
+ }
+ case 'meshes': {
+ for (var m in message.meshes) { obj.meshes[message.meshes[m]._id] = message.meshes[m]; }
+ _Send({ 'action': 'nodes' });
+ break;
+ }
+ case 'nodes': {
+ obj.computerlist.splice(0, obj.computerlist.length); // Clear list
+ for (var m in message.nodes) {
+ if (!obj.meshes[m]) { console.log('Invalid mesh (1): ' + m); continue; }
+ for (var n in message.nodes[m]) {
+ // Build the ComputerList
+ var no = message.nodes[m][n];
+ if (no.intelamt) {
+ //console.log(no.intelamt);
+ var pmode = 0;
+ if ((no.intelamt.flags & 4) != 0) { pmode = 1; } // ACM
+ if ((no.intelamt.flags & 2) != 0) { pmode = 2; } // CCM
+ var computer = { checked: false, h: Math.random(), host: no.host, icon: no.icon, name: no.name, pmode: pmode, pstate: no.intelamt.state, tags: obj.meshes[m].name, ver: no.intelamt.ver, tls: no.intelamt.tls, conn: no.conn, _id: message.nodes[m][n]._id };
+ obj.computerlist.push(computer);
+ }
+ }
+ }
+ // Event node change
+ if (obj.onNodeChange != null) { obj.onNodeChange(this); }
+ break;
+ }
+ case 'event': {
+ switch (message.event.action) {
+ case 'changenode': {
+ for (var i in obj.computerlist) {
+ if (obj.computerlist[i]._id == message.event.nodeid) {
+ var no = message.event.node;
+ var computer = obj.computerlist[i];
+ computer.host = no.host;
+ computer.icon = no.icon;
+ computer.name = no.name;
+ computer.pstate = no.intelamt.state;
+ computer.pmode = 1; // 1 = ACM, 2 = CCM
+ if (obj.meshes[no.meshid]) { computer.tags = obj.meshes[no.meshid].name; }
+ computer.ver = no.intelamt.ver;
+ computer.tls = no.intelamt.tls;
+ if (obj.onNodeChange != null) { obj.onNodeChange(this, computer); }
+ }
+ }
+ break;
+ }
+ case 'nodeconnect': {
+ for (var i in obj.computerlist) {
+ if (obj.computerlist[i]._id == message.event.nodeid) {
+ var computer = obj.computerlist[i];
+ computer.conn = message.event.conn;
+ if (obj.onNodeChange != null) { obj.onNodeChange(this, computer); }
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ // Called when the socket is closed
+ function _OnSocketClosed(cause, msg) {
+ if (obj.socketState == 0) return;
+ obj.socketState = 0;
+ if (obj.onStateChange != null) { obj.onStateChange(obj, obj.socketState, cause, msg); }
+ if (obj.socket != null) { try { obj.socket.end(); } catch (ex) { } obj.socket = null; }
+ obj.meshes = {};
+ obj.userinfo = null;
+ obj.computerlist = [];
+ //console.log('closed');
+ }
+
+ // Called to send websocket data to the server
+ function _Send(object) {
+ if (obj.socketState < 2) { return; }
+ var data = new Buffer(JSON.stringify(object), "binary");
+ var header = String.fromCharCode(129); // 129 is default full fragment op code
+ if (data.length < 126) { header += String.fromCharCode(data.length); }
+ else if (data.length < 65536) { header += String.fromCharCode(126) + ShortToStr(data.length); }
+ else { header += String.fromCharCode(127) + ShortToInt(0) + ShortToInt(data.length); }
+ try { obj.socket.write(new Buffer(header + data, 'binary')); } catch (e) { }
+ }
+
+ // Parse the data and return the decoded HTTP header if present.
+ function parseHttpHeader(data) {
+ var lines = data.split('\r\n');
+ if (lines.length < 1) return null;
+ var values = {}, directive = lines[0].split(' ');
+ if (directive.length < 3) return null;
+ values['_Action'] = directive[0];
+ values['_Path'] = directive[1];
+ values['_Protocol'] = directive[2];
+ for (i in lines) { if (i == 0) continue; var j = lines[i].indexOf(':'); if (j > 0) { values[lines[i].substring(0, j).trim()] = lines[i].substring(j + 1).trim(); } }
+ if (values['Content-Length']) { values['Content-Length'] = parseInt(values['Content-Length']); }
+ return values;
+ }
+
+ return obj;
+}
+
diff --git a/output/Firmware-Large.gz b/output/Firmware-Large.gz
new file mode 100644
index 0000000..7a70c0b
Binary files /dev/null and b/output/Firmware-Large.gz differ
diff --git a/output/Firmware-Medium.gz b/output/Firmware-Medium.gz
new file mode 100644
index 0000000..df0d446
Binary files /dev/null and b/output/Firmware-Medium.gz differ
diff --git a/output/Firmware-Small.gz b/output/Firmware-Small.gz
new file mode 100644
index 0000000..87cbfa7
Binary files /dev/null and b/output/Firmware-Small.gz differ
diff --git a/output/index.htm b/output/index.htm
new file mode 100644
index 0000000..6a7d049
--- /dev/null
+++ b/output/index.htm
@@ -0,0 +1,50840 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
MeshCommander
+
+
+
+
+ Loading...
+
+
+
+
+
+
+
+
+
No known computers
+
Get started by
adding computers or drag & dropping
a computer list file in this window.
+
+
+
+
+
+
+
+
+
+
+
Intel® AMT USB Setup.bin Manager
+
Get started by
creating a new file,
opening an existing one
or drag & dropping a setup.bin file in this window.
+
+
+
+
+
+
+
+
+
Certificate Manager
+
Certificates play an important role in all sorts of Intel® AMT security tasks: TLS network authentication, CIRA configuration, audit log signing and more. Use this panel to create and manage your console certificate.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Floppy, blocks are 512 bytes.
+
+
+
+
CDROM, blocks are 2048 bytes.
+
+
+
+
+
+
+
+
+
+
+
+
Loading...
+
+
+
System Status
+
+
+
+
Hardware Information
+
+
+
+
Event Log
+
+
+
+
+
Network Settings
+
+
+
+
+
User Accounts
+
+
+
+
+
Serial-over-LAN Terminal
+
+
+
Intel® AMT Redirection port or Serial-over-LAN feature is disabled, click here to enable it.
+
+
+
Remote computer is not powered on, click here to issue a power command.
+
+
+
+
+
+
+
Intel® AMT Redirection port or KVM feature is disabled, click here to enable it.
+
+
+
Remote computer is not powered on, click here to issue a power command.
+
+
+
+
+
+
Audit Log
+
+
+
+
Security Settings
+
+
+
+
Internet Settings
+
+
+
+
System Defense
+
+
+
+
Agent Presence
+
+
+
+
Script Editor
+
+
+
+
Script
+
+
+
Compiled Script
+
+
+
+
Variables
+
+
+
Console
+
+
+
+
Storage
+
+
+
+
Event Subscriptions
+
+
+
+
Wake Alarms
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Local Network Any Permission
+
Granted Permissions
+
+
+
*Minimum 8 characters with upper, lowercase, 0-9, and one of !@#$%^&*()+-
+
+
+
+
+
+
+
+
+
+
Digest / None Digest / TLS Kerberos / None Kerberos / TLS Auth / Security
+
+
+
+
*Minimum 8 characters with upper, lowercase, 0-9, and one of !@#$%^&*()+-
+
+
+
+
*Alternate hostname for Kerberos token request
+
+
+
+
+
+
+ Warning: Some power actions may result in data loss and may disconnect the desktop, terminal or disk redirection sessions.
+
+
+
+
+
+
Primary display Secondary display Third display Consent Display
+
+
+
+
+
+ RLE8, Color Fast
+ RLE16, Color
+ RLE4G, Gray Fastest
+ RLE8G, Gray Fast
+ RAW8, Color Slow
+ RAW16, Color Very Slow
+
+
Image Encoding
+
+
+
+
Software KVM
+
+
+ 50%
+ 40%
+ 30%
+ 20%
+ 10%
+ 5%
+ 1%
+
+
Quality
+
+
+
+ 100%
+ 87.5%
+ 75%
+ 62.5%
+ 50%
+ 37.5%
+ 25%
+ 12.5%
+
+
Scaling
+
+
+
+
+
+ Redirection Port
+ KVM Remote Desktop
+ IDE-Redirection
+ Serial-over-LAN
+
+
+ Not Required
+ Required for KVM only
+ Always Required
+
+
+
+
+
+
+
+
+
+
+ WPA2 PSK
+
+ WPA PSK
+
+
+
+
Authentication
+
+
+
+ CCMP-AES
+ TKIP-RC4
+ WEP
+ None
+
+
Encryption
+
+
+
+
+
+ Valid Record
+ Scrambled Record
+
+
+
+
+ Version 1
+ Version 2
+ Version 3
+ Version 4
+
+
Setup.bin version
+
+
+
+ Records will not be consumed
+ Records will be consumed
+
+
Record consumption
+
+
+
+
+
+
+
+
+
+
+
+
+
Use encryption. The file will contain Intel® AMT credentials, saving using a password may help protect this data.
+
+
+
+
+
*Minimum 8 characters with upper, lowercase, 0-9, and one of !@#$%^&*()+-
+
+
+
+ This will save the entire state of Intel® AMT for this machine into file. Passwords will not be saved, but some sensitive data may be included.
+
+
+
+ Disabled
+ ICMP response
+ RMCP response
+ ICMP & RMCP response
+
+
+
+
+
+
+ Disabled
+ Disabled, DHCP update
+ Enabled
+
+
Dynamic DNS client
+
+
+
+
Defaut Interval is 1440 minutes, Default TTL is 900 seconds.
+
+
+
+
+
+ Power up
+ Power cycle
+ Power down
+ Reset
+ OS Wake from Standby
+ OS Power Saving
+ Set boot options
+
+
Remote Command
+
+
+
+
+ None
+ Force CD/DVD Boot
+ Force PXE Boot
+ Force Hard Disk Boot
+ Force Diagnostic Boot
+
+
Boot Source
+
+
+
+ None
+ Index 1
+ Index 2
+ Index 3
+ Index 4
+
+
Boot Media Index
+
+
+
+ Boot to floppy
+ Boot to CDROM
+
+
IDER Boot Device
+
+
+
+ System Default
+ Quiet
+ Verbose
+ Blank Screen
+
+
Verbocity
+
+
+
WARNING: TLS is not used, password will be sent in the clear.
+
+
+
+
+
+
+
+
+
Wake date (year-month-day)
+
+
+
+
+
+
Wake time (hour:min:sec)
+
+
+
+
+
+
Interval (days-hours-min)
+
+
+
+
+ Keep alarm
+ Delete on completion
+
+
+
After wake
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..0025bab
--- /dev/null
+++ b/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "MeshCommander",
+ "version": "0.4.4",
+ "description": "Intel(R) Active Management Technology console tool",
+ "main": "index-nw.html",
+ "author": "Intel Corporation",
+ "keywords": [ "Intel", "Intel AMT", "Active Management Technology", "Remote Management", "Hardware Management", "Manageability Commander" ],
+ "single-instance": false,
+ "window": {
+ "icon": "favicon.png",
+ "toolbar": false,
+ "frame": true,
+ "width": 970,
+ "min_width": 970,
+ "height": 760,
+ "min_height": 640
+ }
+}
\ No newline at end of file
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..c0dde3a
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,59 @@
+MeshCommander
+=============
+
+For more information, [visit MeshCommander.com/meshcommander](https://www.meshcommander.com/meshcommander).
+
+MeshCommander is a Intel(R) Active Management Technology (Intel(R) AMT) remote management tool. It's feature rich and includes a built-in remote desktop viewer for Hardware-KVM, a Serial-over-LAN terminal, IDER-Redirection support and much more. MeshCommander is built on web technologies and runs on many plaforms. In addition to being available as a stand-alone tool, MeshCommander was built to be very space efficient to that it can be uploaded into Intel AMT flash space to have it served diretly from the Intel AMT web serve. There are different ways to install and use MeshCommander.
+
+Windows Installation
+--------------------
+
+On Windows, simply go to [MeshCommander.com/meshcommander](https://www.meshcommander.com/meshcommander) and download and install the MSI installer.
+
+
+NPM Installation
+-----------------
+
+On Windows, Linux and MacOS, you can install MeshCommander from the Node Package Manager (NPM). Once you have NodeJS installed on your computer, you can do:
+
+```
+ mkdir meshcommander
+ cd meshcommander
+ npm install meshcommander
+ node meshcommander
+```
+
+This will start a small web server on port 3000 that you can access using a browser to use MeshCommander at http://127.0.0.1:3000.
+
+
+Firmware Installation
+---------------------
+
+For Intel AMT 11.6 and higher, you can load MeshCommander directly into Intel AMT storage flash space. Depending on the activation mode, MeshCommander can replace the default Intel AMT web page on HTTP/16992 or HTTPS/16993 making the built-in web site much more capable. On Windows, you can download the [firmware installer here](https://www.meshcommander.com/meshcommander/firmware). On other platforms, you can use [MeshCMD](https://www.meshcommander.com/meshcommander/meshcmd) to load MeshCommander into Intel AMT.
+
+
+MeshCMD Installation
+--------------------
+
+On Windows and Linux, you can download [MeshCMD](https://www.meshcommander.com/meshcommander/meshcmd), a command line tool for performing many Intel AMT management operations. Included in that tool is MeshCommander. You can start it up by running:
+
+```
+ meshcmd meshcommander
+```
+
+Like the NPM version, this will start an HTTP web server on port 3000. You can then access http://127.0.0.1:3000 from any browser to access MeshCommander.
+
+
+Tutorials
+---------
+
+There are plenty of [tutorial videos here](https://www.meshcommander.com/meshcommander/tutorials).
+
+Introduction to MeshCommander.
+[](https://www.youtube.com/watch?v=k7xVkZSVY0E)
+
+
+License
+-------
+
+This software is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0).
diff --git a/scriptblocks.txt b/scriptblocks.txt
new file mode 100644
index 0000000..6b26f04
--- /dev/null
+++ b/scriptblocks.txt
@@ -0,0 +1,947 @@
+{
+ "blocks": {
+ "_start": {
+ "name": "Start",
+ "desc": "Starting Block",
+ "code": "print \"Script Started\""
+ },
+ "_end": {
+ "name": "End",
+ "desc": "Ending Block",
+ "code": ":end\r\njump :SkipPullSystemStatus PullSystemStatus \"!=\" 1\r\nPullSystemStatus\r\n:SkipPullSystemStatus\r\njump :SkipPullEventLog PullEventLog \"!=\" 1\r\nPullEventLog\r\n:SkipPullEventLog\r\njump :SkipPullAuditLog PullAuditLog \"!=\" 1\r\nPullAuditLog\r\n:SkipPullAuditLog\r\njump :SkipPullCertificates PullCertificates \"!=\" 1\r\nPullCertificates\r\n:SkipPullCertificates\r\njump :SkipPullWatchdog PullWatchdog \"!=\" 1\r\nPullWatchdog\r\n:SkipPullWatchdog\r\njump :SkipPullSystemDefense PullSystemDefense \"!=\" 1\r\nPullSystemDefense\r\n:SkipPullSystemDefense\r\njump :SkipPullHardware PullHardware \"!=\" 1\r\nPullHardware\r\n:SkipPullHardware\r\njump :SkipPullUserInfo PullUserInfo \"!=\" 1\r\nPullUserInfo\r\n:SkipPullUserInfo\r\njump :SkipPullRemoteAccess PullRemoteAccess \"!=\" 1\r\nPullRemoteAccess\r\n:SkipPullRemoteAccess\r\njump :SkipPullEventSubscriptions PullEventSubscriptions \"!=\" 1\r\npulleventsubscriptions\r\n:SkipPullEventSubscriptions\r\nprint \"Script Completed\""
+ },
+ "AMT-Accounts-AddDigestUser": {
+ "name": "Accounts - Add Digest User",
+ "desc": "Add a new digest user account to Intel AMT",
+ "code": "# Get the DigestRealm\r\njump :SkipDigestRealm-%%%~%%% DigestRealm \"!=\"\r\nprint \"Fetching digest realm...\"\r\nsplit ws_general_query \"*AMT_GeneralSettings\" ,\r\nwsbatchenum \"wsman_answer\" ws_general_query\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nset DigestRealm wsman_answer.AMT_GeneralSettings.response.DigestRealm\r\n:SkipDigestRealm-%%%~%%%\r\n\r\n# Create account\r\nset AccountName \"%%%name%%%\"\r\nset AccountPass \"%%%password%%%\"\r\nset digest \"{AccountName}:{DigestRealm}:{AccountPass}\"\r\nmd5 digestmd5 digest\r\nbtoa digestmd5 digestmd5\r\njsonparse wsargs \"%7B %22DigestUsername%22:%22{AccountName}%22, %22DigestPassword%22:%22{digestmd5}%22, %22AccessPermission%22:%%%accessPermission%%%, %22Realms%22:[%%%realms%%%] %7D\"\r\nwsexec \"AMT_AuthorizationService\" \"AddUserAclEntryEx\" wsargs \"\"\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nprint \"Account {AccountName} create: {AMT_AuthorizationService.Body.ReturnValueStr}\"\r\n\r\nset PullUserInfo 1\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"Call failed: {wsman_result_str}\"\r\n:end-%%%~%%%",
+ "vars": {
+ "name": {
+ "name": "Name",
+ "desc": "Name of the user account to create",
+ "type": 1,
+ "maxlength": 30,
+ "value": ""
+ },
+ "password": {
+ "name": "Password",
+ "desc": "Password of the user account to create",
+ "type": 4,
+ "maxlength": 30,
+ "value": ""
+ },
+ "accessPermission": {
+ "name": "Access Permission",
+ "desc": "Set account to be local, remote or both",
+ "type": 3,
+ "values": {
+ "0": "Local only",
+ "1": "Network only",
+ "2": "All (Local & Network)"
+ },
+ "value": "2"
+ },
+ "realms": {
+ "name": "Realms",
+ "desc": "Set account permissions",
+ "type": 5,
+ "values": {
+ "2": "Redirection",
+ "3": "PT Administration",
+ "4": "Hardware Asset",
+ "5": "Remote Control",
+ "6": "Storage",
+ "7": "Event Manager",
+ "8": "Storage Admin",
+ "9": "Agent Presence Local",
+ "10": "Agent Presence Remote",
+ "11": "Circuit Breaker",
+ "12": "Network Time",
+ "13": "General Information",
+ "14": "Firmware Update",
+ "15": "EIT",
+ "16": "LocalUN",
+ "17": "Endpoint Access Control",
+ "18": "Endpoint Access Control Admin",
+ "19": "Event Log Reader",
+ "20": "Audit Log",
+ "21": "ACL Realm",
+ "24": "Local System"
+ },
+ "value": [ "3" ]
+ }
+ }
+ },
+ "AMT-Accounts-RemoveDigestUser": {
+ "name": "Accounts - Remove Digest User",
+ "desc": "Remove a digest user account from Intel AMT",
+ "code": "set ToggleAccount \"%%%name%%%\"\r\n\r\n# Fetch all of the account handles\r\nprint \"Fetching account handles...\"\r\njsonparse wsargs \"%7B %22StartIndex%22:1 %7D\"\r\nwsexec \"AMT_AuthorizationService\" \"EnumerateUserAclEntries\" wsargs \"\"\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nset AccountHandles AMT_AuthorizationService.Body.Handles\r\nset wsargs\r\nset AMT_AuthorizationService\r\nset wsman_result\r\nset wsman_result_str\r\nlength AccountHandlesCount AccountHandles\r\n\r\n# Get all of the account information\r\nprint \"Fetching all account information...\"\r\nset i 0\r\n:fetchAccountLoop-%%%~%%%\r\nset fetchHandle AccountHandles.{i}\r\njsonparse wsargs \"%7B %22Handle%22:{fetchHandle} %7D\"\r\nwsexec \"AMT_AuthorizationService\" \"GetAclEnabledState\" wsargs \"\"\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nset AccountEnabled{i} AMT_AuthorizationService.Body.Enabled\r\nwsexec \"AMT_AuthorizationService\" \"GetUserAclEntryEx\" wsargs \"\"\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nset AccountName{i} AMT_AuthorizationService.Body.DigestUsername\r\nset AccountAccess{i} AMT_AuthorizationService.Body.AccessPermission\r\nset AccountRealms{i} AMT_AuthorizationService.Body.Realms\r\nadd i i 1\r\njump :fetchAccountLoop-%%%~%%% i \"<\" AccountHandlesCount\r\nset AMT_AuthorizationService\r\nset fetchHandle\r\nset wsargs\r\n\r\n# Search for a matching account\r\nprint \"Searching accounts...\"\r\nset i 0\r\n:searchAccountLoop-%%%~%%%\r\nset searchHandle AccountHandles.{i}\r\njump :foundAccount AccountName{i} \"=\" ToggleAccount\r\nadd i i 1\r\njump :searchAccountLoop-%%%~%%% i \"<\" AccountHandlesCount\r\njump :end-%%%~%%%\r\n\r\n# Account found, delete it\r\n:foundAccount\r\nprint \"Account {ToggleAccount} found at index {i}, deleting it...\"\r\nset deleteHandle AccountHandles.{i}\r\njsonparse wsargs \"%7B %22Handle%22:{deleteHandle} %7D\"\r\nwsexec \"AMT_AuthorizationService\" \"RemoveUserAclEntry\" wsargs \"\"\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nprint \"Done, account {ToggleAccount} deleted.\"\r\nset PullUserInfo 1\r\njump :end-%%%~%%%\r\n\r\n# End of script\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"Call failed: {wsman_result_str}\"\r\n:end-%%%~%%%",
+ "vars": {
+ "name": {
+ "name": "Name",
+ "desc": "Name of the user account to remove",
+ "type": 1,
+ "maxlength": 30,
+ "value": ""
+ }
+ }
+ },
+ "AMT-Accounts-AddKerberosUser": {
+ "name": "Accounts - Add Kerberos User",
+ "desc": "Add a new kerberos user account to Intel AMT",
+ "code": "# Set kerberos sid value as a byte array string\r\nset KerberosUserString \"%%%sid%%%\"\r\nGetSidByteArray x KerberosUserString\r\nbtoa KerberosUserSid x\r\njsonparse wsargs \"%7B%22KerberosUserSid%22:%22{KerberosUserSid}%22,%22AccessPermission%22:%%%accessPermission%%%,%22Realms%22:[%%%realms%%%]%7D\"\r\nwsexec \"AMT_AuthorizationService\" \"AddUserAclEntryEx\" wsargs \"\"\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nprint \"Account {KerberosUserString} return value: {AMT_AuthorizationService.Body.ReturnValueStr}\"\r\n\r\nset PullUserInfo 1\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"Call failed: {wsman_result_str}\"\r\n:end-%%%~%%%",
+ "vars": {
+ "sid": {
+ "name": "Sid",
+ "desc": "The Security ID (SID) of the user account to create",
+ "type": 1,
+ "maxlength": 45,
+ "value": ""
+ },
+ "accessPermission": {
+ "name": "Access Permission",
+ "desc": "Set account to be local, remote or both",
+ "type": 3,
+ "values": {
+ "0": "Local only",
+ "1": "Network only",
+ "2": "All (Local & Network)"
+ },
+ "value": "2"
+ },
+ "realms": {
+ "name": "Realms",
+ "desc": "Set account permissions",
+ "type": 5,
+ "values": {
+ "2": "Redirection",
+ "3": "PT Administration",
+ "4": "Hardware Asset",
+ "5": "Remote Control",
+ "6": "Storage",
+ "7": "Event Manager",
+ "8": "Storage Admin",
+ "9": "Agent Presence Local",
+ "10": "Agent Presence Remote",
+ "11": "Circuit Breaker",
+ "12": "Network Time",
+ "13": "General Information",
+ "14": "Firmware Update",
+ "15": "EIT",
+ "16": "LocalUN",
+ "17": "Endpoint Access Control",
+ "18": "Endpoint Access Control Admin",
+ "19": "Event Log Reader",
+ "20": "Audit Log",
+ "21": "ACL Realm",
+ "24": "Local System"
+ },
+ "value": [ "3" ]
+ }
+ }
+ },
+ "AMT-Accounts-RemoveKerberosUser": {
+ "name": "Accounts - Remove Kerberos User",
+ "desc": "Remove a digest user account from Intel AMT",
+ "code": "GetSidByteArray ToggleAccount \"%%%sid%%%\"\r\nbtoa ToggleAccount ToggleAccount\r\n# Fetch all of the account handles\r\nprint \"Fetching account handles...\"\r\njsonparse wsargs \"%7B %22StartIndex%22:1 %7D\"\r\nwsexec \"AMT_AuthorizationService\" \"EnumerateUserAclEntries\" wsargs \"\"\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nset AccountHandles AMT_AuthorizationService.Body.Handles\r\nset wsargs\r\nset AMT_AuthorizationService\r\nset wsman_result\r\nset wsman_result_str\r\nlength AccountHandlesCount AccountHandles\r\n\r\n# Get all of the account information\r\nprint \"Fetching all account information...\"\r\nset i 0\r\n:fetchAccountLoop-%%%~%%%\r\nset fetchHandle AccountHandles.{i}\r\njsonparse wsargs \"%7B %22Handle%22:{fetchHandle} %7D\"\r\nwsexec \"AMT_AuthorizationService\" \"GetAclEnabledState\" wsargs \"\"\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nset AccountEnabled{i} AMT_AuthorizationService.Body.Enabled\r\nwsexec \"AMT_AuthorizationService\" \"GetUserAclEntryEx\" wsargs \"\"\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nset AccountName{i} AMT_AuthorizationService.Body.KerberosUserSid\r\nset AccountAccess{i} AMT_AuthorizationService.Body.AccessPermission\r\nset AccountRealms{i} AMT_AuthorizationService.Body.Realms\r\nadd i i 1\r\njump :fetchAccountLoop-%%%~%%% i \"<\" AccountHandlesCount\r\nset AMT_AuthorizationService\r\nset fetchHandle\r\nset wsargs\r\n\r\n# Search for a matching account\r\nprint \"Searching accounts...\"\r\nset i 0\r\n:searchAccountLoop-%%%~%%%\r\nset searchHandle AccountHandles.{i}\r\njump :foundAccount AccountName{i} \"=\" ToggleAccount\r\nadd i i 1\r\njump :searchAccountLoop-%%%~%%% i \"<\" AccountHandlesCount\r\njump :end-%%%~%%%\r\n\r\n# Account found, delete it\r\n:foundAccount\r\nprint \"Account %%%sid%%% found at index {i}, deleting it...\"\r\nset deleteHandle AccountHandles.{i}\r\njsonparse wsargs \"%7B %22Handle%22:{deleteHandle} %7D\"\r\nwsexec \"AMT_AuthorizationService\" \"RemoveUserAclEntry\" wsargs \"\"\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nprint \"Done, account %%%sid%%% deleted.\"\r\nset PullUserInfo 1\r\njump :end-%%%~%%%\r\n\r\n# End of script\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"Call failed: {wsman_result_str}\"\r\n:end-%%%~%%%",
+ "vars": {
+ "sid": {
+ "name": "Sid",
+ "desc": "Sid of the user account to remove",
+ "type": 1,
+ "maxlength": 45,
+ "value": ""
+ }
+ }
+ },
+ "AMT-Accounts-PrintAll": {
+ "name": "Accounts - Print Users",
+ "desc": "Display all digest user accounts from Intel AMT",
+ "code": "# Fetch all of the account handles\r\nprint \"Fetching account handles...\"\r\njsonparse wsargs \"%7B %22StartIndex%22:1 %7D\"\r\nwsexec \"AMT_AuthorizationService\" \"EnumerateUserAclEntries\" wsargs \"\"\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nset AccountHandles AMT_AuthorizationService.Body.Handles\r\nset wsargs\r\nset AMT_AuthorizationService\r\nset wsman_result\r\nset wsman_result_str\r\nlength AccountHandlesCount AccountHandles\r\n\r\n# Get all of the account information\r\nprint \"Fetching all account information...\"\r\nset i 0\r\n:fetchAccountLoop-%%%~%%%\r\nset fetchHandle AccountHandles.{i}\r\njsonparse wsargs \"%7B %22Handle%22:{fetchHandle} %7D\"\r\nwsexec \"AMT_AuthorizationService\" \"GetAclEnabledState\" wsargs \"\"\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nset AccountEnabled{i} AMT_AuthorizationService.Body.Enabled\r\nwsexec \"AMT_AuthorizationService\" \"GetUserAclEntryEx\" wsargs \"\"\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nprint \"AMT-ACCOUNT: {AMT_AuthorizationService.Body.DigestUsername}, {AMT_AuthorizationService.Body.AccessPermission}, [{AMT_AuthorizationService.Body.Realms}]\"\r\nadd i i 1\r\njump :fetchAccountLoop-%%%~%%% i \"<\" AccountHandlesCount\r\nset AMT_AuthorizationService\r\nset fetchHandle\r\nset wsargs\r\n\r\n# End of script\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"Call failed: {wsman_result_str}\"\r\n:end-%%%~%%%"
+ },
+ "Basic-Add": {
+ "name": "Basic - Add",
+ "desc": "Add a value to a given variable",
+ "code": "add %%%var%%% %%%var%%% %%%value%%%",
+ "vars": {
+ "var": {
+ "name": "Name",
+ "desc": "Name of the variable to add to",
+ "type": 1,
+ "maxlength": 20,
+ "value": "SampleVariable"
+ },
+ "value": {
+ "name": "Value",
+ "desc": "Value to add to the variable",
+ "type": 1,
+ "value": "1"
+ }
+ }
+ },
+ "Basic-Disconnect": {
+ "name": "Basic - Disconnect",
+ "desc": "Disconnect from Intel AMT",
+ "code": "Disconnect"
+ },
+ "Basic-JumpLabel": {
+ "name": "Basic - Jump Target",
+ "desc": "Set a jump label. Other blocks can jump here.",
+ "code": ":%%%label%%%",
+ "vars": {
+ "label": {
+ "name": "Label",
+ "desc": "Name of the jump target label",
+ "type": 1,
+ "maxlength": 50,
+ "value": "SampleLabel"
+ }
+ }
+ },
+ "Basic-Jump": {
+ "name": "Basic - Jump",
+ "desc": "Jump to a given label",
+ "code": "jump :%%%label%%%",
+ "vars": {
+ "label": {
+ "name": "Label",
+ "desc": "Name of the jump target label",
+ "type": 1,
+ "maxlength": 50,
+ "value": "SampleLabel"
+ }
+ }
+ },
+ "Basic-JumpIf": {
+ "name": "Basic - Jump if",
+ "desc": "Jump to a given label if the condition is met",
+ "code": "jump :%%%label%%% %%%arg1%%% \"%%%comparator%%%\" %%%arg2%%%",
+ "vars": {
+ "label": {
+ "name": "Label",
+ "desc": "Name of the jump target label",
+ "type": 1,
+ "maxlength": 50,
+ "value": "SampleLabel"
+ },
+ "arg1": {
+ "name": "arg1",
+ "desc": "First variable to compare, use \"x\" for a string",
+ "type": 1,
+ "value": ""
+ },
+ "comparator": {
+ "name": "Comparator",
+ "desc": "How to compare both arguments",
+ "type": 3,
+ "values": {
+ "=": "=",
+ "!=": "!=",
+ "<": "<",
+ ">": ">",
+ "<=": "<=",
+ ">=": ">="
+ },
+ "value": "="
+ },
+ "arg2": {
+ "name": "arg2",
+ "desc": "Second variable to compare, use \"x\" for a string",
+ "type": 1,
+ "value": ""
+ }
+ }
+ },
+ "Basic-Print": {
+ "name": "Basic - Print",
+ "desc": "Print a string to the console",
+ "code": "print \"%%%printstring%%%\"",
+ "vars": {
+ "printstring": {
+ "name": "Value",
+ "desc": "String that will be printed to console, use urlescaping for special chars and use {x} to print variable x.",
+ "type": 1,
+ "value": "Sample String"
+ }
+ }
+ },
+ "Basic-ScriptSpeed": {
+ "name": "Basic - Script Speed",
+ "desc": "Set the speed of the script",
+ "code": "scriptspeed %%%delay%%%",
+ "vars": {
+ "delay": {
+ "name": "Delay",
+ "desc": "The delay in millisecond between execution of each script step. 200ms is 5 steps per second.",
+ "type": 2,
+ "maxlength": 4,
+ "value": 200
+ }
+ }
+ },
+ "Basic-Set": {
+ "name": "Basic - Set",
+ "desc": "Set a variable to a given value",
+ "code": "set %%%var%%% %%%value%%%",
+ "vars": {
+ "var": {
+ "name": "Name",
+ "desc": "Name of the variable to set",
+ "type": 1,
+ "maxlength": 20,
+ "value": "SampleVariable"
+ },
+ "value": {
+ "name": "Value",
+ "desc": "The new value to set to the variable",
+ "type": 1,
+ "value": "0"
+ }
+ }
+ },
+ "AMT-Event-RemoveAllSubscription": {
+ "name": "Event - Remove All Subscriptions",
+ "desc": "Remove all subscriptions.",
+ "vars": { },
+ "code": "# Fetch all of subscriptions handles\nprint \"Deleting all event subscriptions...\"\nsplit ws_query \"CIM_ListenerDestination,CIM_FilterCollectionSubscription\" \",\"\nwsbatchenum \"wsman_answer\" ws_query\njump :error-%%%~%%% wsman_result \"!=\" 200\nlength i wsman_answer.CIM_ListenerDestination.responses\n:loop-%%%~%%%\njump :end-%%%~%%% i \"<=\" 0\nsubstract i i 1\nprint \"Delete {i}\"\nset name wsman_answer.CIM_ListenerDestination.responses.{i}.Name\nset filter wsman_answer.CIM_FilterCollectionSubscription.responses.{i}.Filter.ReferenceParameters.SelectorSet.Selector.Value\njsonparse r \"%7B%22Filter%22:%22
http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_FilterCollection {filter} %22, %22Handler%22:%22
http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous http://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ListenerDestinationWSManagement CIM_ListenerDestinationWSMAN {name} CIM_ComputerSystem Intel(r) AMT %22%7D\"\nwsunsubscribe \"CIM_FilterCollectionSubscription\" r\nprint \"Result: {wsman_result}\"\njump :loop-%%%~%%% i \"!=\" 0\n# End of script\njump :end-%%%~%%%\n:error-%%%~%%%\nprint \"Call failed: {wsman_result_str}\"\n:end-%%%~%%%\nset i\nset r\nset name\nset filter\nset ws_query\nset wsman_answer\nset PullEventSubscriptions 1\n##!BLOCK!##"
+ },
+ "AMT-Event-AddSubscription": {
+ "name": "Event - Add Subscription",
+ "desc": "Add a subscription event to Intel AMT.",
+ "vars": {
+ "SubscriptionType": {
+ "name": "Type",
+ "desc": "Type of subscription",
+ "type": "3",
+ "value": "Push",
+ "values": {
+ "Push": "Push",
+ "PushWithAck": "Push with ACK"
+ }
+ },
+ "SubscriptionFilter": {
+ "name": "Filter",
+ "desc": "Event filter, only the selected event types will be sent.",
+ "type": "3",
+ "value": "1",
+ "values": {
+ "0": "ME Presence Events",
+ "1": "User Notification",
+ "2": "All Events",
+ "3": "Platform Events",
+ "4": "Core Platform Events",
+ "5": "Features",
+ "6": "System Firmware Progress Events"
+ }
+ },
+ "SubscriptionUrl": {
+ "name": "URL",
+ "desc": "URL used to send events to.",
+ "type": "1",
+ "maxlength": "255",
+ "value": "http://"
+ },
+ "SubscriptionArgs": {
+ "name": "Arguments",
+ "desc": "Extra arguments sent when sending the event.",
+ "type": "1",
+ "maxlength": "255",
+ "value": ""
+ }
+ },
+ "code": "print \"Adding subscription: %%%SubscriptionUrl%%%\"\nsplit filters \"Intel(r) AMT:ME Presence,Intel(r) AMT:User,Intel(r) AMT:All,Intel(r) AMT:Platform,Intel(r) AMT:CorePlatform,Intel(r) AMT:Features,Intel(r) AMT:FW ProgressEvents\" \",\"\nset filter filters.%%%SubscriptionFilter%%%\njsonparse subfilter \"%7B%22InstanceID%22:%22{filter}%22%7D\"\nwssubscribe \"CIM_FilterCollection\" \"%%%SubscriptionType%%%\" \"%%%SubscriptionUrl%%%\" subfilter \"%%%SubscriptionArgs%%%\"\n\n# End of script\njump :end-%%%~%%%\n:error-%%%~%%%\nprint \"Call failed: {wsman_result_str}\"\n:end-%%%~%%%\nset filters\nset filter\nset subfilter\nset PullEventSubscriptions 1\n"
+ },
+ "AMT-General-SetUserConsent": {
+ "name": "General - Set User Consent",
+ "desc": "Set the Intel AMT user consent mode",
+ "code": "split ws_optIn_query \"*IPS_OptInService\" ,\r\nwsbatchenum \"wsman_answer\" ws_optIn_query\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nset wsman_answer.IPS_OptInService.response.OptInRequired %%%consentMode%%%\r\nwsput \"IPS_OptInService\" wsman_answer.IPS_OptInService.response\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nset PullSystemStatus 1\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"Call failed: {wsman_result_str}\"\r\n:end-%%%~%%%\r\n",
+ "vars": {
+ "consentMode": {
+ "name": "Consent Mode",
+ "desc": "Intel AMT user consent mode",
+ "type": 3,
+ "values": {
+ "0": "Not Required",
+ "1": "Required for KVM only",
+ "0xFFFFFFFF": "Always Required"
+ },
+ "value": "0"
+ }
+ }
+ },
+ "AMT-General-ActiveFeatures": {
+ "name": "General - Set Active Features",
+ "desc": "Set the Intel AMT active features",
+ "code": "split ws_optIn_query \"*AMT_RedirectionService\" ,\r\nwsbatchenum \"wsman_answer\" ws_optIn_query\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nset wsman_answer.AMT_RedirectionService.response.ListenerEnabled \"%%%listenerEnabled%%%\"\r\nset wsman_answer.AMT_RedirectionService.response.EnabledState \"%%%enabledState%%%\"\r\njsonparse wsargs \"%7B %22RequestedState%22:%22%%%enabledState%%%%22 %7D\"\r\nwsexec \"AMT_RedirectionService\" \"RequestStateChange\" wsargs\r\nwsput \"AMT_RedirectionService\" wsman_answer.AMT_RedirectionService.response\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nset PullSystemStatus \"1\"\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"Call failed: {wsman_result_str}\"\r\n:end-%%%~%%%\r\n",
+ "vars": {
+ "listenerEnabled": {
+ "name": "Redirection Port",
+ "desc": "Enable or disable the Intel AMT redirection port (TCP:16993/16995)",
+ "type": 3,
+ "values": {
+ "true": "Enabled",
+ "false": "Disabled"
+ },
+ "value": "true"
+ },
+ "enabledState": {
+ "name": "SOL/IDER Feature",
+ "desc": "Enable or disable the Intel AMT Serial-over-LAN and IDER features",
+ "type": 3,
+ "values": {
+ "32768": "Disabled",
+ "32769": "IDER only",
+ "32770": "Serial-over-LAN only",
+ "32771": "IDER & SOL enabled"
+ },
+ "value": "32771"
+ }
+ }
+ },
+ "AMT-General-GetCoreVersion": {
+ "name": "General - Get Version",
+ "desc": "Retrieves the Intel AMT release version, prints it to the console and stores it in variable AmtCoreVersion",
+ "code": "split ws_general_query \"CIM_SoftwareIdentity\"\r\nwsbatchenum \"wsman_answer\" ws_general_query\r\nset i 0\r\nset arr wsman_answer.CIM_SoftwareIdentity.responses\r\nlength arr_len arr\r\n:loop-%%%~%%%\r\nset curInstanceId arr.{i}.InstanceID\r\njump :AmtCoreVersionFound-%%%~%%% curInstanceId \"=\" \"AMT FW Core Version\"\r\nadd i i 1\r\njump :loop-%%%~%%% i \"<\" arr_len\r\nprint \"Error: Intel AMT version was not found\"\r\njump :end-%%%~%%%\r\n:AmtCoreVersionFound-%%%~%%%\r\nset AmtCoreVersion arr.{i}.VersionString\r\nprint \"Intel AMT version: {AmtCoreVersion}\"\r\n:end-%%%~%%%\r\nset arr\r\nset arr_len\r\nset curInstanceId\r\nset i\r\nset ws_general_query\r\nset wsman_answer\r\nset wsman_result"
+ },
+ "AMT-General-GetPlatformType": {
+ "name": "General - Get Platform Type",
+ "desc": "Retrieves the platfrom type of the target, prints it to the console and stores it in variable PlatformType",
+ "code": "jsonparse sysTypeHmap \"%7B%2232%22:%22Desktop%22,%2233%22:%22Notebook%22%7D\"\r\nsplit ws_general_query \"CIM_ComputerSystem\"\r\nwsbatchenum \"wsman_answer\" ws_general_query\r\nset i -1\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\ngetitem i wsman_answer.CIM_ComputerSystem.responses \"ElementName\" \"Managed System\"\r\njump :amtCoreError-%%%~%%% i \"<\" 0\r\nset i wsman_answer.CIM_ComputerSystem.responses.{i}.Dedicated\r\nset PlatformType sysTypeHmap.{i}\r\nprint \"Platform Type: {PlatformType}\"\r\njump :end-%%%~%%%\r\n:amtCoreError-%%%~%%%\r\nprint \"Error: couldn't find CIM_ComputerSystem.ElementName = %22Managed System%22\"\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"WSMAN call failed: {wsman_result_str}\"\r\n:end-%%%~%%%\r\nset i\r\nset ws_general_query\r\nset wsman_answer\r\nset wsman_result\r\nset wsman_result_str\r\nset sysTypeHmap"
+ },
+ "AMT-General-GetProvState": {
+ "name": "General - Get Provisisoning State",
+ "desc": "Retrieves the current Provisioning State of Intel AMT, prints it to the console and stores it in variable AmtProvState",
+ "code": "jsonparse provStateHmap \"%7B%220%22:%22Pre%22,%221%22:%22In%22,%222%22:%22Post%22%7D\"\r\nsplit ws_general_query \"*AMT_SetupAndConfigurationService\"\r\nwsbatchenum \"wsman_answer\" ws_general_query\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nset key wsman_answer.AMT_SetupAndConfigurationService.response.ProvisioningState\r\nset AmtProvState provStateHmap.{key}\r\nadd AmtProvState AmtProvState \"-Provisioning\"\r\nprint \"Intel AMT Provisioning State: {AmtProvState}\"\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"WSMAN call failed: {wsman_result_str}\"\r\n:end-%%%~%%%\r\nset ws_general_query\r\nset wsman_answer\r\nset wsman_result\r\nset wsman_result_str\r\nset provStateHmap\r\nset key"
+ },
+ "AMT-General-GetProvMode": {
+ "name": "General - Get Provisisoning Mode",
+ "desc": "Retrieves the current Provisioning Mode of Intel AMT, prints it to the console and stores it in variable AmtProvMode",
+ "code": "jsonparse provModeHmap \"%7B%221%22:%22Admin%20Control%20Mode%20(ACM)%22,%222%22:%22Reserved1%22,%223%22:%22Client%20Control%20Mode%20(CCM)%22,%224%22:%22Reserved2%22%7D\"\r\nsplit ws_general_query \"*AMT_SetupAndConfigurationService\"\r\nwsbatchenum \"wsman_answer\" ws_general_query\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nset key wsman_answer.AMT_SetupAndConfigurationService.response.ProvisioningMode\r\nset AmtProvMode provModeHmap.{key}\r\nprint \"Intel AMT Provisioning Mode: {AmtProvMode}\"\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"WSMAN call failed: {wsman_result_str}\"\r\n:end-%%%~%%%\r\nset ws_general_query\r\nset wsman_answer\r\nset wsman_result\r\nset wsman_result_str\r\nset provModeHmap\r\nset key"
+ },
+ "AMT-General-PrintUserConsent": {
+ "name": "General - Print User Consent",
+ "desc": "Display the Intel AMT user consent mode",
+ "code": "jsonparse OptInStateEnum \"%7B%220%22:%22Not Required%22,%221%22:%22Required for KVM only%22,%224294967295%22:%22Always Required%22%7D\"\r\nsplit ws_optIn_query \"*IPS_OptInService\" ,\r\nwsbatchenum \"wsman_answer\" ws_optIn_query\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nprint \"User Consent mode: {OptInStateEnum.{wsman_answer.IPS_OptInService.response.OptInRequired}}\"\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"Call failed: {wsman_result_str}\"\r\n:end-%%%~%%%\r\n"
+ },
+ "AMT-General-SetHostname": {
+ "name": "General - Set Hostname",
+ "desc": "Set the Intel AMT KVM feature to enabled or disabled",
+ "code": "split ws_general_query \"*AMT_GeneralSettings\" ,\r\nwsbatchenum \"wsman_answer\" ws_general_query\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nset wsman_answer.AMT_GeneralSettings.response.HostName \"%%%hostname%%%\"\r\nset wsman_answer.AMT_GeneralSettings.response.DomainName \"%%%domainname%%%\"\r\nwsput \"AMT_GeneralSettings\" wsman_answer.AMT_GeneralSettings.response\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nset PullSystemStatus \"1\"\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"Call failed: {wsman_result_str}\"\r\n:end-%%%~%%%\r\n",
+ "vars": {
+ "hostname": {
+ "name": "Hostname",
+ "desc": "The hostname Intel AMT will use while in Sx state",
+ "type": 1,
+ "maxlength": 30,
+ "value": ""
+ },
+ "domainname": {
+ "name": "Domain",
+ "desc": "The domain name Intel AMT will use while in Sx state",
+ "type": 1,
+ "maxlength": 30,
+ "value": ""
+ }
+ }
+ },
+ "AMT-General-SetPingResponse": {
+ "name": "General - Set Ping Response",
+ "desc": "Set the Intel AMT response to ICMP and RMCP ping requests",
+ "code": "split ws_general_query \"*AMT_GeneralSettings\" ,\r\nwsbatchenum \"wsman_answer\" ws_general_query\r\njump :error-2 wsman_result \"!=\" 200\r\nset wsman_answer.AMT_GeneralSettings.response.PingResponseEnabled \"%%%icmpPingResponse%%%\"\r\nset wsman_answer.AMT_GeneralSettings.response.RmcpPingResponseEnabled \"%%%rmcpPingResponse%%%\"\r\nwsput \"AMT_GeneralSettings\" wsman_answer.AMT_GeneralSettings.response\r\njump :error-2 wsman_result \"!=\" 200\r\nset PullSystemStatus \"1\"\r\njump :end-2\r\n:error-2\r\nprint \"Call failed: {wsman_result_str}\"\r\n:end-2\r\n",
+ "vars": {
+ "icmpPingResponse": {
+ "name": "ICMP Ping",
+ "desc": "Enable or disable the Intel AMT response to ICMP ping",
+ "type": 3,
+ "values": {
+ "true": "Enabled",
+ "false": "Disabled"
+ },
+ "value": "true"
+ },
+ "rmcpPingResponse": {
+ "name": "RMCP Ping",
+ "desc": "Enable or disable the Intel AMT response to RMCP ping",
+ "type": 3,
+ "values": {
+ "true": "Enabled",
+ "false": "Disabled"
+ },
+ "value": "true"
+ }
+ }
+ },
+ "AMT-General-GetAmtUuid": {
+ "name": "General - Get UUID",
+ "desc": "Retrieves the Intel AMT UUID, prints it to the console and stores it in variable AmtUuid",
+ "code": "split ws_general_query \"CIM_ComputerSystem\"\r\nwsbatchenum \"wsman_answer\" ws_general_query\r\nset i -1\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\ngetitem i wsman_answer.CIM_ComputerSystem.responses \"ElementName\" \"Managed System\"\r\njump :amtCoreError-%%%~%%% i \"<\" 0\r\nset AmtUuid wsman_answer.CIM_ComputerSystem.responses.{i}.OtherIdentifyingInfo\r\nprint \"Intel AMT UUID: {AmtUuid}\"\r\njump :end-%%%~%%%\r\n:amtCoreError-%%%~%%%\r\nprint \"Error: couldn't find CIM_ComputerSystem.ElementName = %22Managed System%22\"\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"WSMAN call failed: {wsman_result_str}\"\r\n:end-%%%~%%%\r\nset i\r\nset ws_general_query\r\nset wsman_answer\r\nset wsman_result"
+ },
+ "AMT-KVM-SetState": {
+ "name": "KVM - Set State",
+ "desc": "Set the Intel AMT KVM feature to enabled or disabled",
+ "code": "jsonparse wsargs \"%7B %22RequestedState%22:%22%%%kvmEnabled%%%%22 %7D\"\r\nwsexec \"CIM_KVMRedirectionSAP\" \"RequestStateChange\" wsargs\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nset PullSystemStatus \"1\"\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"Call failed: {wsman_result_str}\"\r\n:end-%%%~%%%\r\n",
+ "vars": {
+ "kvmEnabled": {
+ "name": "KVM State",
+ "desc": "Enable or disable the Intel AMT KVM feature",
+ "type": 3,
+ "values": {
+ "2": "Enabled",
+ "3": "Disabled"
+ },
+ "value": "2"
+ }
+ }
+ },
+ "AMT-KVM-SetSessionTimeout": {
+ "name": "KVM - Set Session Timeout",
+ "desc": "Set the Intel AMT KVM session timeout",
+ "vars": {
+ "kvmTimeout": {
+ "name": "KVM Timeout",
+ "desc": "Intel AMT KVM session timeout in minutes",
+ "type": "2",
+ "value": "4"
+ }
+ },
+ "code": "split ws_general_query \"*IPS_KVMRedirectionSettingData\" ,\nwsbatchenum \"wsman_answer\" ws_general_query\njump :error-%%%~%%% wsman_result \"!=\" 200\nset wsman_answer.IPS_KVMRedirectionSettingData.response.SessionTimeout \"%%%kvmTimeout%%%\"\nwsput \"IPS_KVMRedirectionSettingData\" wsman_answer.IPS_KVMRedirectionSettingData.response\njump :error-%%%~%%% wsman_result \"!=\" 200\nset PullSystemStatus \"1\"\njump :end-%%%~%%%\n:error-%%%~%%%\nprint \"Call failed: {wsman_result_str}\"\n:end-%%%~%%%\n\n"
+ },
+ "AMT-Network-DetectWiredNic": {
+ "name": "Network - Wired NIC",
+ "desc": "Detects if the platfrom has a wired Intel AMT network interface controller (NIC), logs to the console and stores the result in WiredAmtNic",
+ "code": "split ws_general_query \"CIM_EthernetPort\"\r\nwsbatchenum \"wsman_answer\" ws_general_query\r\nset i -1\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\ngetitem i wsman_answer.CIM_EthernetPort.responses \"DeviceID\" \"Intel(r) AMT Ethernet Port 0\"\r\njump :amtCoreError-%%%~%%% i \"<\" 0\r\nset WiredAmtNic \"true\"\r\nprint \"Wired AMT NIC found: true\"\r\njump :end-%%%~%%%\r\n:amtCoreError-%%%~%%%\r\nprint \"Wired AMT NIC found: false\"\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"WSMAN call failed: {wsman_result_str}\"\r\n:end-%%%~%%%\r\nset i\r\nset ws_general_query\r\nset wsman_answer\r\nset wsman_result"
+ },
+ "AMT-Network-DetectWifiNic": {
+ "name": "Network - Wireless NIC",
+ "desc": "Detects if the platfrom has a WiFi interface, logs to the console and stores the result in WiFiAmtNic",
+ "code": "split ws_general_query \"CIM_EthernetPort\"\r\nwsbatchenum \"wsman_answer\" ws_general_query\r\nset i -1\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\ngetitem i wsman_answer.CIM_EthernetPort.responses \"DeviceID\" \"Intel(r) AMT Ethernet Port 1\"\r\njump :amtCoreError-%%%~%%% i \"<\" 0\r\nset WiFiAmtNic \"true\"\r\nprint \"WiFi AMT NIC found: true\"\r\njump :end-%%%~%%%\r\n:amtCoreError-%%%~%%%\r\nprint \"Wifi AMT NIC found: false\"\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"WSMAN call failed: {wsman_result_str}\"\r\n:end-%%%~%%%\r\nset i\r\nset ws_general_query\r\nset wsman_answer\r\nset wsman_result"
+ },
+ "AMT-Network-GetAmtFqdn": {
+ "name": "Network - Get FQDN",
+ "desc": "Retrieves the FQDN of Intel AMT, prints it to the console and stores it in variable AmtFqdn",
+ "code": "split ws_general_query \"*AMT_GeneralSettings\"\r\nwsbatchenum \"wsman_answer\" ws_general_query\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nset AmtFqdn wsman_answer.AMT_GeneralSettings.response.HostName\r\nadd AmtFqdn AmtFqdn \".\"\r\nadd AmtFqdn AmtFqdn wsman_answer.AMT_GeneralSettings.response.DomainName\r\nprint \"Intel AMT FQDN: {AmtFqdn}\"\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"WSMAN call failed: {wsman_result_str}\"\r\n:end-%%%~%%%\r\nset ws_general_query\r\nset wsman_answer\r\nset wsman_result"
+ },
+ "AMT-Network-AddEnvDetection": {
+ "name": "Network - Set Environment Detection",
+ "desc": "Configures the DNS information that will be used by Intel AMT to dynamically determine the network it is operating in",
+ "code": "# *** Validate user input ***\r\nprint \"Parsing block parameters\"\r\njump :EMPTY_DETECTIONSTR-%%%~%%% \"%%%DetectionStrings%%%\" \"=\" \"\"\r\nsplit arrDetectionStrings \"%%%DetectionStrings%%%\" \",\"\r\nsplit arrDetectionIPv6LocalPrefixes \"%%%DetectionIPv6LocalPrefixes%%%\" \",\"\r\nprint \"Setting Environment Detection\"\r\nsplit ws_general_query \"*AMT_EnvironmentDetectionSettingData\" \",\"\r\nwsbatchenum \"wsman_answer\" ws_general_query\r\nset envDetectionInstance wsman_answer.AMT_EnvironmentDetectionSettingData.response\r\njump :DetectionStringsDefined-%%%~%%% envDetectionInstance.DetectionStrings \"!=\"\r\nset envDetectionInstance.DetectionStrings arrDetectionStrings\r\njump :SET_IPV6_PREFIX-%%%~%%%\r\n:DetectionStringsDefined-%%%~%%%\r\nadd arrDetectionStrings \",\" arrDetectionStrings\r\nadd envDetectionInstance.DetectionStrings envDetectionInstance.DetectionStrings arrDetectionStrings\r\nmaketoarray envDetectionInstance.DetectionStrings envDetectionInstance.DetectionStrings\r\nlength arrDetectionStringsLen envDetectionInstance.DetectionStrings\r\njump :INVALID_LEN_DetectionStrings-%%%~%%% arrDetectionStringsLen \">\" \"5\"\r\n:SET_IPV6_PREFIX-%%%~%%%\r\njump :IPv6StringsDefined-%%%~%%% envDetectionInstance.DetectionIPv6LocalPrefixes \"!=\"\r\njump :EMPTY_IPV6PRFX \"%%%DetectionIPv6LocalPrefixes%%%\" \"=\" \"\" \r\nset envDetectionInstance.DetectionIPv6LocalPrefixes arrDetectionIPv6LocalPrefixes\r\njump :CALL_WSPUT-%%%~%%%\r\n:IPv6StringsDefined-%%%~%%%\r\nadd arrDetectionIPv6LocalPrefixes \",\" arrDetectionIPv6LocalPrefixes\r\nadd envDetectionInstance.DetectionIPv6LocalPrefixes envDetectionInstance.DetectionIPv6LocalPrefixes arrDetectionIPv6LocalPrefixes\r\nmaketoarray envDetectionInstance.DetectionIPv6LocalPrefixes envDetectionInstance.DetectionIPv6LocalPrefixes\r\n:EMPTY_IPV6PRFX\r\nlength arrDetectionIPv6LocalPrefixesLen envDetectionInstance.DetectionIPv6LocalPrefixes\r\njump :INVALID_LEN_DetectionIPv6LocalPrefixes-%%%~%%% arrDetectionIPv6LocalPrefixesLen \">\" \"5\"\r\n:CALL_WSPUT-%%%~%%%\r\nwsput \"AMT_EnvironmentDetectionSettingData\" envDetectionInstance\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nprint \"Environment Detection set successfully\"\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"ERROR: WSMAN call failed: {wsman_result_str}\"\r\njump :end-%%%~%%%\r\n:INVALID_LEN_DetectionStrings-%%%~%%%\r\nprint \"ERROR: detection strings count must be at most 5\"\r\njump :end-%%%~%%%\r\n:INVALID_LEN_DetectionIPv6LocalPrefixes-%%%~%%%\r\nprint \"ERROR: IPv6 prefixes count must be at most 5\"\r\njump :end-%%%~%%%\r\n:EMPTY_DETECTIONSTR-%%%~%%%\r\nprint \"ERROR: %22Detection Strings%22 field cannot be empty, aborting operation...\"\r\n:end-%%%~%%%\r\n set PullRemoteAccess \"1\"\r\nset AMT_EnvironmentDetectionSettingData\r\nset arrDetectionIPv6LocalPrefixes\r\nset arrDetectionStrings\r\nset envDetectionInstance\r\nset ws_general_query\r\nset wsman_answer \r\nset wsman_result",
+ "vars": {
+ "DetectionStrings": {
+ "name": "Detection Strings",
+ "desc": "A comma separated list of up to 4 strings to use in the environment detection algorithm (e.g. intel.com,contoso.com)",
+ "type": 1,
+ "maxlength": 255,
+ "value": ""
+ },
+ "DetectionIPv6LocalPrefixes": {
+ "name": "IPv6 Local Prefixes",
+ "desc": "A comma separated list of IPv6 local prefixes (strings) to use independently of or in conjunction with Detection Strings. (e.g. 1234::/64,4321::/46)",
+ "type": 1,
+ "maxlength": 255,
+ "value": ""
+ }
+ }
+ },
+ "AMT-Network-ClearEnvDetection": {
+ "name": "Network - Clear Environment Detection",
+ "desc": "Clears the DNS information that is used by Intel AMT to dynamically determine the network it is operating in",
+ "vars": { },
+ "code": "split ws_general_query \"*AMT_EnvironmentDetectionSettingData\" \",\"\nwsbatchenum \"wsman_answer\" ws_general_query\nset envDetectionInstance wsman_answer.AMT_EnvironmentDetectionSettingData.response\nset envDetectionInstance.DetectionStrings undefined\nwsput \"AMT_EnvironmentDetectionSettingData\" envDetectionInstance\njump :error-%%%~%%% wsman_result \"==\" 200\nprint \"Cleared environment detection\"\njump :end-%%%~%%%\n:error-%%%~%%%\nprint \"ERROR: WSMAN call failed: {wsman_result_str}\"\njump :end-%%%~%%%\n:end-%%%~%%%\nset envDetectionInstance\nset ws_general_query\nset AMT_EnvironmentDetectionSettingData\nset PullRemoteAccess \"1\"\nset wsman_answer \nset wsman_result\n"
+ },
+ "AMT-SetBoot-PowerAction": {
+ "name": "Power - Power Action",
+ "desc": "Perform an Intel AMT power action",
+ "code": "set ManagedElementXml \"%3CAddress xmlns=\\%22http://schemas.xmlsoap.org/ws/2004/08/addressing\\%22%3Ehttp://schemas.xmlsoap.org/ws/2004/08/addressing%3C/Address%3E%3CReferenceParameters xmlns=\\%22http://schemas.xmlsoap.org/ws/2004/08/addressing\\%22%3E%3CResourceURI xmlns=\\%22http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd\\%22%3Ehttp://schemas.dmtf.org/wbem/wscim/1/cim-schema/2/CIM_ComputerSystem%3C/ResourceURI%3E%3CSelectorSet xmlns=\\%22http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd\\%22%3E%3CSelector Name=\\%22CreationClassName\\%22%3ECIM_ComputerSystem%3C/Selector%3E%3CSelector Name=\\%22Name\\%22%3EManagedSystem%3C/Selector%3E%3C/SelectorSet%3E%3C/ReferenceParameters%3E\"\r\njsonparse wsargs \"%7B %22PowerState%22:%22%%%powerAction%%%%22, %22ManagedElement%22:%22{ManagedElementXml}%22 %7D\"\r\nset ManagedElementXml\r\nwsexec \"CIM_PowerManagementService\" \"RequestPowerStateChange\" wsargs\r\nset wsargs\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nset PullSystemStatus \"1\"\r\nprint \"Power action completed\"\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"Call failed: {wsman_result_str}\"\r\n:end-%%%~%%%\r\n",
+ "vars": {
+ "powerAction": {
+ "name": "Power Action",
+ "desc": "Indicate the power action to perform",
+ "type": 3,
+ "values": {
+ "2": "Power on",
+ "5": "Power cycle",
+ "8": "Power down",
+ "10": "Reset"
+ },
+ "value": "2"
+ }
+ }
+ },
+ "AMT-Power-SetBootSettings": {
+ "name": "Power - Set Boot Settings",
+ "desc": "Set next boot parameters",
+ "code": "split ws_general_query \"*AMT_BootSettingData\"\nwsbatchenum \"wsman_answer\" ws_general_query\njump :error-%%%~%%% wsman_result \"!=\" 200\nset bootoptions wsman_answer.AMT_BootSettingData.response\nset bootoptions.BIOSSetup \"%%%bootBiosSetup%%%\"\nset bootoptions.UseSOL \"%%%bootSerialOverLan%%%\"\nwsput \"AMT_BootSettingData\" bootoptions\nset AMT_BootSettingData\njump :error-%%%~%%% wsman_result \"!=\" 200\njump :end-%%%~%%%\n:error-%%%~%%%\nprint \"WSMAN call failed: {wsman_result_str}\"\n:end-%%%~%%%\nset ws_general_query\nset wsman_answer\nset wsman_result\nset wsman_result_str\n#set bootoptions\n\n",
+ "vars": {
+ "bootBiosSetup": {
+ "name": "BIOS Setup",
+ "desc": "On next boot go to BIOS setup screen",
+ "type": "3",
+ "value": "false",
+ "values": {
+ "true": "Enabled",
+ "false": "Disabled"
+ }
+ },
+ "bootSerialOverLan": {
+ "name": "Serial-over-LAN",
+ "desc": "Enable Serial-over-LAN on next boot",
+ "type": "3",
+ "value": "false",
+ "values": {
+ "true": "Enabled",
+ "false": "Disabled"
+ }
+ }
+ }
+ },
+ "AMT-Power-GetBootSettings": {
+ "name": "Power - Get Boot Settings",
+ "desc": "Get next boot parameters",
+ "code": "split ws_general_query \"*AMT_BootSettingData\"\nwsbatchenum \"wsman_answer\" ws_general_query\njump :error-%%%~%%% wsman_result \"!=\" 200\nset bootoptions wsman_answer.AMT_BootSettingData.response\nprint bootoptions\nset AMT_BootSettingData\njump :error-%%%~%%% wsman_result \"!=\" 200\njump :end-%%%~%%%\n:error-%%%~%%%\nprint \"WSMAN call failed: {wsman_result_str}\"\n:end-%%%~%%%\nset ws_general_query\nset wsman_answer\nset wsman_result\nset wsman_result_str\n#set bootoptions\n",
+ "vars": { }
+ },
+ "AMT-RemoteAccess-AddMpsServerFqdnCert": {
+ "name": "Remote - Add MPS FQDN/Cert",
+ "desc": "Add a new CIRA server (MPS) using the server's hostname and authentication using certificate",
+ "code": "# Get the input from user for the CN to look for\r\n# Get available certificates\r\nsplit ws_general_query \"AMT_PublicKeyCertificate\" ,\r\nwsbatchenum \"wsman_answer\" ws_general_query\r\nlength wsman_ans_length wsman_answer.AMT_PublicKeyCertificate.responses\r\nset i 0\r\n:loop_ans-%%%~%%%\r\n# Get the current subject name\r\nset curSubject wsman_answer.AMT_PublicKeyCertificate.responses.{i}.Subject\r\nIndexOf pos curSubject \"CN=%%%CN%%%\" \r\njump :cnFound-%%%~%%% pos \">=\" 0\r\nadd i i 1\r\njump :loop_ans-%%%~%%% i \"<\" wsman_ans_length\r\njump :cnNotFound-%%%~%%%\r\n:cnFound-%%%~%%%\r\n# Set the reference to the certificate\r\nset certInstanceId wsman_answer.AMT_PublicKeyCertificate.responses.{i}.InstanceID\r\nset certHandle \"%3CAddress%20xmlns=%22http://schemas.xmlsoap.org/ws/2004/08/addressing%22%3Ehttp://schemas.xmlsoap.org/ws/2004/08/addressing%3C/Address%3E%3CReferenceParameters%20xmlns=%22http://schemas.xmlsoap.org/ws/2004/08/addressing%22%3E%3CResourceURI%20xmlns=%22http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd%22%3Ehttp://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate%3C/ResourceURI%3E%3CSelectorSet%20xmlns=%22http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd%22%3E%3CSelector%20Name=%22InstanceID%22%3E{certInstanceId}%3C/Selector%3E%3C/SelectorSet%3E%3C/ReferenceParameters%3E\"\r\n# Set method parameters\r\njsonparse wsargs \"%7B%22AccessInfo%22:%22%%%FQDN%%%%22,%22InfoFormat%22:%22201%22,%22Port%22:%%%Port%%%,%22AuthMethod%22:%221%22%7D\"\r\nset wsargs.Certificate certHandle\r\n# Execute call to AddMpServer\r\nwsexec \"AMT_RemoteAccessService\" \"AddMpServer\" wsargs \"\"\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nprint \"Management Prescence Server (MPS) successfully added to the Intel(R) AMT Subsystem\"\r\nset PullRemoteAccess 1\r\njump :end-%%%~%%%\r\n:cnNotFound-%%%~%%%\r\nprint \"Couldn't find a certificate matching the value of CN=%%%CN%%%\"\r\n:error-%%%~%%%\r\nprint \"Call failed with error {wsman_result}\"\r\n:end-%%%~%%%\r\nset AMT_RemoteAccessService\r\nset certHandle\r\nset curSubject\r\nset i\r\nset pos\r\nset ws_general_query\r\nset wsargs\r\nset wsman_answer\r\nset wsman_result\r\nset wsman_result_str\r\nset certInstanceId\r\nset wsman_ans_length",
+ "vars": {
+ "FQDN": {
+ "name": "MPS Hostname",
+ "desc": "The Fully Qualified Domain Name of the MPS to add",
+ "type": 1,
+ "maxlength": 255,
+ "value": ""
+ },
+ "Port": {
+ "name": "Port Number",
+ "desc": "The MPS server port number",
+ "type": 2,
+ "maxlength": 5,
+ "value": ""
+ },
+ "CN": {
+ "name": "Certificate CN",
+ "desc": "The common name of the authentication certificate",
+ "type": 1,
+ "maxlength": 100,
+ "value": ""
+ }
+ }
+ },
+ "AMT-RemoteAccess-AddMpsServerFqdnUpa": {
+ "name": "Remote - Add MPS FQDN/User",
+ "desc": "Add a new CIRA server (MPS) using the server's hostname authentication using username/password",
+ "code": "# Set method parameters\r\njsonparse wsargs \"%7B%22AccessInfo%22:%22%%%FQDN%%%%22,%22InfoFormat%22:201,%22Port%22:%%%Port%%%,%22AuthMethod%22:2,%22Username%22:%22%%%username%%%%22,%22Password%22:%22%%%password%%%%22%7D\"\r\n# Execute call to AddMpServer\r\nwsexec \"AMT_RemoteAccessService\" \"AddMpServer\" wsargs \"\"\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nprint \"Management Prescence Server (MPS) successfully added to the Intel(R) AMT Subsystem\"\r\nset PullRemoteAccess 1\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"Call failed: {wsman_result_str}\"\r\n:end-%%%~%%%\r\nset AMT_RemoteAccessService\r\nset certHandle\r\nset curSubject\r\nset i\r\nset pos\r\nset ws_general_query\r\nset wsargs\r\nset wsman_answer\r\nset wsman_result\r\nset wsman_result_str\r\nset certInstanceId\r\nset wsman_ans_length",
+ "vars": {
+ "FQDN": {
+ "name": "MPS Hostname",
+ "desc": "The Fully Qualified Domain Name of the MPS to add",
+ "type": 1,
+ "maxlength": 255,
+ "value": ""
+ },
+ "Port": {
+ "name": "Port Number",
+ "desc": "The MPS server port number",
+ "type": 2,
+ "maxlength": 5,
+ "value": ""
+ },
+ "username": {
+ "name": "Username",
+ "desc": "A Username to be used for the connection with the MPS",
+ "type": 1,
+ "maxlength": 16,
+ "value": ""
+ },
+ "password": {
+ "name": "Password",
+ "desc": "The Password matching the username above",
+ "type": 4,
+ "maxlength": 16,
+ "value": ""
+ }
+ }
+ },
+ "AMT-RemoteAccess-AddMpsIpCertServer": {
+ "name": "Remote - Add MPS IP/Cert",
+ "desc": "Add a new CIRA server (MPS) using the server's IP address and authentication using certificate",
+ "code": "# Get the input from user for the CN to look for\r\n# Get available certificates\r\nsplit ws_general_query \"AMT_PublicKeyCertificate\" ,\r\nwsbatchenum \"wsman_answer\" ws_general_query\r\nlength wsman_ans_length wsman_answer.AMT_PublicKeyCertificate.responses\r\nset i 0\r\n:loop_ans-%%%~%%%\r\n# Get the current subject name\r\nset curSubject wsman_answer.AMT_PublicKeyCertificate.responses.{i}.Subject\r\nIndexOf pos curSubject \"CN=%%%CN%%%\" \r\njump :cnFound-%%%~%%% pos \">=\" 0\r\nadd i i 1\r\njump :loop_ans-%%%~%%% i \"<\" wsman_ans_length\r\njump :cnNotFound-%%%~%%%\r\n:cnFound-%%%~%%%\r\n# Set the reference to the certificate\r\nset certInstanceId wsman_answer.AMT_PublicKeyCertificate.responses.{i}.InstanceID\r\nset certHandle \"%3CAddress%20xmlns=%22http://schemas.xmlsoap.org/ws/2004/08/addressing%22%3Ehttp://schemas.xmlsoap.org/ws/2004/08/addressing%3C/Address%3E%3CReferenceParameters%20xmlns=%22http://schemas.xmlsoap.org/ws/2004/08/addressing%22%3E%3CResourceURI%20xmlns=%22http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd%22%3Ehttp://intel.com/wbem/wscim/1/amt-schema/1/AMT_PublicKeyCertificate%3C/ResourceURI%3E%3CSelectorSet%20xmlns=%22http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd%22%3E%3CSelector%20Name=%22InstanceID%22%3E{certInstanceId}%3C/Selector%3E%3C/SelectorSet%3E%3C/ReferenceParameters%3E\"\r\n# Set method parameters\r\njsonparse wsargs \"%7B%22AccessInfo%22:%22%%%IP%%%%22,%22InfoFormat%22:%223%22,%22Port%22:%%%Port%%%,%22AuthMethod%22:%221%22%7D\"\r\nset wsargs.Certificate certHandle\r\nset wsargs.CN \"%%%ServerName%%%\"\r\n# Execute call to AddMpServer\r\nwsexec \"AMT_RemoteAccessService\" \"AddMpServer\" wsargs \"\"\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nprint \"Management Prescence Server (MPS) successfully added to the Intel(R) AMT Subsystem\"\r\nset PullRemoteAccess 1\r\njump :end-%%%~%%%\r\n:cnNotFound-%%%~%%%\r\nprint \"Couldn't find a certificate matching the value of CN=%%%CN%%%\"\r\n:error-%%%~%%%\r\nprint \"Call failed: {wsman_result_str}\"\r\n:end-%%%~%%%\r\nset AMT_RemoteAccessService\r\nset certHandle\r\nset curSubject\r\nset i\r\nset pos\r\nset ws_general_query\r\nset wsargs\r\nset wsman_answer\r\nset wsman_result\r\nset wsman_result_str\r\nset certInstanceId\r\nset wsman_ans_length",
+ "vars": {
+ "IP": {
+ "name": "IPv4 Address",
+ "desc": "The IPv4 address of the MPS server",
+ "type": 1,
+ "maxlength": 255,
+ "value": ""
+ },
+ "Port": {
+ "name": "Port Number",
+ "desc": "The MPS server port number",
+ "type": 2,
+ "maxlength": 5,
+ "value": ""
+ },
+ "ServerName": {
+ "name": "Server Name",
+ "desc": "The server name, this must be the exact Common Name in the MPS server certificate",
+ "type": 1,
+ "maxlength": 255,
+ "value": ""
+ },
+ "CN": {
+ "name": "Certificate CN",
+ "desc": "The common name of the authentication certificate",
+ "type": 1,
+ "maxlength": 100,
+ "value": ""
+ }
+ }
+ },
+ "AMT-RemoteAccess-AddMpsIpUpa": {
+ "name": "Remote - Add MPS IP/User",
+ "desc": "Add a new CIRA server (MPS) using the servers IP address and authenticating using a username/password",
+ "code": "# Set method parameters\r\njsonparse wsargs \"%7B%22AccessInfo%22:%22%%%IP%%%%22,%22InfoFormat%22:%223%22,%22Port%22:%%%Port%%%,%22AuthMethod%22:%222%22,%22Username%22:%22%%%username%%%%22,%22Password%22:%22%%%password%%%%22%7D\"\r\nset wsargs.CN \"%%%ServerName%%%\"\r\n# Execute call to AddMpServer\r\nwsexec \"AMT_RemoteAccessService\" \"AddMpServer\" wsargs \"\"\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nprint \"Management Prescence Server (MPS) successfully added to the Intel(R) AMT Subsystem\"\r\nset PullRemoteAccess 1\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"Call failed: {wsman_result_str}\"\r\n:end-%%%~%%%\r\nset AMT_RemoteAccessService\r\nset wsargs\r\nset wsman_answer\r\nset wsman_result\r\nset wsman_result_str\r\nset wsman_ans_length",
+ "vars": {
+ "IP": {
+ "name": "IPv4 Address",
+ "desc": "The IPv4 address of the MPS server",
+ "type": 1,
+ "maxlength": 255,
+ "value": ""
+ },
+ "Port": {
+ "name": "Port Number",
+ "desc": "The MPS server port number",
+ "type": 2,
+ "maxlength": 5,
+ "value": ""
+ },
+ "ServerName": {
+ "name": "Server Name",
+ "desc": "The server name, this must be the exact Common Name in the MPS server certificate",
+ "type": 1,
+ "maxlength": 255,
+ "value": ""
+ },
+ "username": {
+ "name": "Username",
+ "desc": "A Username to be used for the connection with the MPS",
+ "type": 1,
+ "maxlength": 16,
+ "value": ""
+ },
+ "password": {
+ "name": "Password",
+ "desc": "The Password matching the username above",
+ "type": 4,
+ "maxlength": 16,
+ "value": ""
+ }
+ }
+ },
+ "AMT-RemoteAccess-Remove-MPS": {
+ "name": "Remote - Remove MPS",
+ "desc": "Remove MPS identified by its IP/FQDN and port",
+ "code": "split ws_general_query \"AMT_ManagementPresenceRemoteSAP\" ,\r\nwsbatchenum \"wsman_answer\" ws_general_query\r\nset i 0\r\nset arr wsman_answer.AMT_ManagementPresenceRemoteSAP.responses\r\nLength arr_len arr\r\n:loop-%%%~%%%\r\nset curAccessInfo arr.{i}.AccessInfo\r\nadd curAccessInfo curAccessInfo \":\"\r\nadd curAccessInfo curAccessInfo arr.{i}.Port\r\njump :mpsFound-%%%~%%% curAccessInfo \"=\" \"%%%AccessInfo%%%:%%%Port%%%\"\r\nadd i i 1\r\njump :loop-%%%~%%% i \"<\" arr_len\r\nprint \"No MPS was found matching the input parameters\"\r\njump :end-%%%~%%%\r\n:mpsFound-%%%~%%%\r\nprint \"Found matching MPS, starting removal process\"\r\nset instanceName wsman_answer.AMT_ManagementPresenceRemoteSAP.responses.{i}.Name\r\nset selector \"%3Cw:SelectorSet%3E%3Cw:Selector%20Name=%22Name%22%3E{instanceName}%3C/w:Selector%3E%3C/w:SelectorSet%3E\"\r\nwsdelete \"AMT_ManagementPresenceRemoteSAP\" selector\r\n:end-%%%~%%%\r\nset AMT_ManagementPresenceRemoteSAP\r\nset arr\r\nset curAccessInfo\r\nset i\r\nset instanceName\r\nset selector\r\nset ws_general_query\r\nset wsman_answer\r\nset wsman_result\r\nset wsman_result_str\r\nset arr_len\r\nset PullRemoteAccess 1",
+ "vars": {
+ "AccessInfo": {
+ "name": "FQDN/Address",
+ "desc": "The FQDN/IPv4 address of the MPS server to be deleted",
+ "type": 1,
+ "maxlength": 255,
+ "value": ""
+ },
+ "Port": {
+ "name": "Port Number",
+ "desc": "The MPS server port number",
+ "type": 2,
+ "maxlength": 5,
+ "value": ""
+ }
+ }
+ },
+ "AMT-RemoteAccess-RemoveAll-MPS": {
+ "name": "Remote - Remove All MPS",
+ "desc": "Remove all MPS",
+ "vars": { },
+ "code": "split ws_general_query \"AMT_ManagementPresenceRemoteSAP\" ,\nwsbatchenum \"wsman_answer\" ws_general_query\nset i 0\nset arr wsman_answer.AMT_ManagementPresenceRemoteSAP.responses\nLength arr_len arr\n:loop-%%%~%%%\nset instanceName wsman_answer.AMT_ManagementPresenceRemoteSAP.responses.{i}.Name\nset selector \"%3Cw:SelectorSet%3E%3Cw:Selector%20Name=%22Name%22%3E{instanceName}%3C/w:Selector%3E%3C/w:SelectorSet%3E\"\nwsdelete \"AMT_ManagementPresenceRemoteSAP\" selector\nadd i i 1\njump :loop-%%%~%%% i \"<\" arr_len\n:end-%%%~%%%\nset AMT_ManagementPresenceRemoteSAP\nset arr\nset i\nset instanceName\nset selector\nset ws_general_query\nset wsman_answer\nset wsman_result\nset wsman_result_str\nset arr_len\nset PullRemoteAccess 1\n"
+ },
+ "AMT-RemoteAccess-AddRemoteAccessPolicyRule": {
+ "name": "Remote - Add Trigger (User / Alert)",
+ "desc": "Set a remote access trigger policy, used to establish a secure tunnel between a management console and the Intel AMT platform.",
+ "code": "# *** Prepare arguments for AMT_RemoteAccessService.AddRemoteAccessPolicyRule ***\r\njsonparse ws_args \"%7B%22Trigger%22:%220%22,%22TunnelLifeTime%22:%22%%%tLifeTime%%%%22%7D\"\r\n# *** Verify valid input ***\r\njump :VALID_INPUT \"%%%AccessInfo1%%%\" \"!=\" \"\"\r\nprint \"ERROR: Field %22AccessInfo1%22 must not be empty, aborting operation...\"\r\njump :end-%%%~%%%\r\n:VALID_INPUT\r\n# *** Set a EPR selector matching user input ***\r\nsplit ws_general_query \"AMT_ManagementPresenceRemoteSAP\" ,\r\nwsbatchenum \"wsman_answer\" ws_general_query\r\nset i 0\r\nset arr wsman_answer.AMT_ManagementPresenceRemoteSAP.responses\r\nLength arr_len arr\r\nset mpsEpr1 \"*\"\r\nset mpsEpr2 \"*\"\r\n:loop-%%%~%%%\r\nset curAccessInfo arr.{i}.AccessInfo\r\nadd curAccessInfo curAccessInfo \":\"\r\nadd curAccessInfo curAccessInfo arr.{i}.Port\r\njump :MPS1_NO_MATCH curAccessInfo \"!=\" \"%%%AccessInfo1%%%\"\r\nset mpsEpr1 wsman_answer.AMT_ManagementPresenceRemoteSAP.responses.{i}.Name\r\nprint \"Found matching (primary) mps: {mpsEpr1}\"\r\njump :MPS2_NOTSET \"%%%AccessInfo2%%%\" \"=\" \"\"\r\n:MPS1_NO_MATCH\r\njump :MPS2_NO_MATCH curAccessInfo \"!=\" \"%%%AccessInfo2%%%\"\r\nset mpsEpr2 wsman_answer.AMT_ManagementPresenceRemoteSAP.responses.{i}.Name\r\nprint \"Found matching (secondary) mps: {mpsEpr2}\"\r\n:MPS2_NO_MATCH\r\nadd i i 1\r\njump :loop-%%%~%%% i \"<\" arr_len\r\n:MPS2_NOTSET\r\njump :MPS1_FOUND mpsEpr1 \"!=\" \"*\"\r\nprint \"ERROR: MPS server: %22%%%AccessInfo1%%%%22 could not be found, aborting operation...\"\r\njump :end-%%%~%%%\r\n:MPS1_FOUND\r\njump :MPS2_FOUND \"%%%AccessInfo2%%%\" \"=\" \"\"\r\njump :MPS2_FOUND mpsEpr2 \"!=\" \"*\"\r\nprint \"ERROR: MPS server: %22%%%AccessInfo2%%%%22 could not be found, aborting operation...\"\r\njump :end-%%%~%%%\r\n:MPS2_FOUND\r\nprint \"Setting policy...\"\r\njsonparse ws_args.MpServer \"%7B%7D\"\r\nset MpServer \"%3CAddress%20xmlns=%22http://schemas.xmlsoap.org/ws/2004/08/addressing%22%3Ehttp://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous%3C/Address%3E%3CReferenceParameters%20xmlns=%22http://schemas.xmlsoap.org/ws/2004/08/addressing%22%3E%3CResourceURI%20xmlns=%22http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd%22%3Ehttp://intel.com/wbem/wscim/1/amt-schema/1/AMT_ManagementPresenceRemoteSAP%3C/ResourceURI%3E%3CSelectorSet%20xmlns=%22http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd%22%3E%3CSelector%20Name=%22Name%22%3E{mpsEpr1}%3C/Selector%3E%3C/SelectorSet%3E%3C/ReferenceParameters%3E\"\r\njump :SKIP_ADD_MPS2 \"%%%AccessInfo2%%%\" \"=\" \"\"\r\nadd MpServer MpServer \"|%3CAddress%20xmlns=%22http://schemas.xmlsoap.org/ws/2004/08/addressing%22%3Ehttp://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous%3C/Address%3E%3CReferenceParameters%20xmlns=%22http://schemas.xmlsoap.org/ws/2004/08/addressing%22%3E%3CResourceURI%20xmlns=%22http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd%22%3Ehttp://intel.com/wbem/wscim/1/amt-schema/1/AMT_ManagementPresenceRemoteSAP%3C/ResourceURI%3E%3CSelectorSet%20xmlns=%22http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd%22%3E%3CSelector%20Name=%22Name%22%3E{mpsEpr2}%3C/Selector%3E%3C/SelectorSet%3E%3C/ReferenceParameters%3E\"\r\n:SKIP_ADD_MPS2\r\nsplit ws_args.MpServer MpServer \"|\"\r\n# *** Call AMT_RemoteAccessService.AddRemoteAccessPolicyRule with policy details. ***\r\nwsexec \"AMT_RemoteAccessService\" \"AddRemoteAccessPolicyRule\" ws_args selector\r\njump :error-%%%~%%% wsman_result \"!=\" 200\r\nprint \"Policy added successfully\"\r\njump :end-%%%~%%%\r\n:error-%%%~%%%\r\nprint \"WSMAN call failed: {wsman_result_str}\"\r\n:end-%%%~%%%\r\nset PullRemoteAccess 1\r\nset mpsEpr1\r\nset mpsEpr2\r\nset i\r\nset curAccessInfo\r\nset arr_len\r\nset MpServer\r\nset arr\r\nset AMT_RemoteAccessService\r\nset wsman_result\r\nset wsman_result_str\r\nset ws_args\r\nset ws_general_query\r\nset wsman_answer",
+ "vars": {
+ "AccessInfo1": {
+ "name": "MPS 1 Address",
+ "desc": "The FQDN/IPv4 & Port of the MPS targeted for this policy. (e.g. mps1.mydomain.com:1234, 1.2.3.4:2233)",
+ "type": 1,
+ "maxlength": 255,
+ "value": ""
+ },
+ "AccessInfo2": {
+ "name": "MPS 2 Address",
+ "desc": "Optional, leave empty value if not applicable. Sames as above. In case you wish to apply this policy to 2 (two) mps instances",
+ "type": 1,
+ "maxlength": 255,
+ "value": ""
+ },
+ "Trigger": {
+ "name": "Trigger",
+ "desc": "The event that will trigger the establishment of the remote connection to the MPS.",
+ "type": 3,
+ "values": {
+ "0": "User Initiated",
+ "1": "Alert"
+ },
+ "value": "0"
+ },
+ "tLifeTime": {
+ "name": "Tunnel Lifetime",
+ "desc": "Defines the tunnel’s lifetime in seconds. A value of 0 means that the tunnel should stay open until it is closed by the server, the CloseRemoteAccessConnection method or when a different policy with a higher priority needs to be processed.",
+ "type": 2,
+ "maxlength": 5,
+ "value": "0"
+ }
+ }
+ },
+ "AMT-RemoteAccess-AddRemoteAccessPolicyRule2": {
+ "name": "Remote - Add Trigger (Periodic)",
+ "desc": "Set a remote access trigger policy, used to establish a secure tunnel between a management console and the Intel AMT platform.",
+ "code": "# *** Verify valid input ***\r\nsplit period_arr \"%%%Period%%%\" \":\"\r\nlength period_arr_len period_arr\r\njump :INVALID_ARG_AccessInfo1 \"%%%AccessInfo1%%%\" \"=\" \"\"\r\njump :DailyPeriod \"%%%PeriodType%%%\" \"!=\" \"0\"\r\njump :INVALID_PeriodType \"%%%PeriodType%%%\" \"!=\" \"0\"\r\njump :INVALID_ARG_Period period_arr.0 \"<=\" \"0\"\r\njump :INVALID_ARG_Period period_arr.0 \">\" \"4294967295\"\r\nIntToStr extendedData \"0\"\r\nIntToStr bPeriod period_arr.0\r\nadd extendedData extendedData bPeriod\r\njump :SET_PERIOD\r\n:DailyPeriod\r\njump :INVALID_PeriodType period_arr_len \"!=\" \"2\"\r\njump :INVALID_ARG_PeriodDaily period_arr.0 \"<=\" \"0\"\r\njump :INVALID_ARG_PeriodDaily period_arr.0 \">\" \"23\"\r\njump :INVALID_ARG_PeriodDaily period_arr.1 \">\" \"59\"\r\njump :INVALID_ARG_PeriodDaily period_arr.1 \"<=\" \"0\"\r\nIntToStr extendedData \"1\"\r\nIntToStr bPeriodHour period_arr.0\r\nIntToStr bPeriodMinute period_arr.1\r\nadd extendedData extendedData bPeriodHour\r\nadd extendedData extendedData bPeriodMinute\r\njump :SET_PERIOD\r\n:INVALID_PeriodType\r\nprint \"ERROR: The period type and value must correspond, aborting operation...\"\r\njump :end-%%%~%%%\r\n:INVALID_ARG_PeriodDaily\r\nprint \"ERROR: Field %22Period%22 must be a value HH:MM 0<=HH<24 && 0<=MM<60, aborting operation...\"\r\njump :end-%%%~%%%\r\n:INVALID_ARG_AccessInfo1\r\nprint \"ERROR: Field %22AccessInfo1%22 must not be empty, aborting operation...\"\r\njump :end-%%%~%%%\r\n:INVALID_ARG_Period\r\nprint \"ERROR: Field %22Period%22 must be a value 0<=t
+
+
+
+
+
\ No newline at end of file
diff --git a/webrelay.ashx b/webrelay.ashx
new file mode 100644
index 0000000..f4ae753
--- /dev/null
+++ b/webrelay.ashx
@@ -0,0 +1,175 @@
+<%@ WebHandler Language="C#" Class="ManageabilityCommander.WebRelay" %>
+
+using System;
+using System.IO;
+using System.Net;
+using System.Web;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Collections;
+using System.Net.Sockets;
+using System.Net.Security;
+using System.Web.WebSockets;
+using System.Net.WebSockets;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+using System.Security.Cryptography;
+using System.Security.Authentication;
+using System.Security.Cryptography.X509Certificates;
+
+namespace ManageabilityCommander
+{
+ ///
+ /// WebSocket to TCP/TLS bridge. This handler accepts a websocket connection and forwards the traffic to TCP/TLS.
+ ///
+ public class WebRelay : IHttpHandler
+ {
+ string host = null;
+ int port = 0;
+ bool tls = false;
+ WebSocket websocket = null;
+ TcpClient client = null;
+ Stream stream = null;
+ byte[] clientReadBuf = new byte[16384];
+ bool closing = false;
+ object mainlock = new object();
+
+ public bool IsReusable { get { return false; } }
+ private void Log(string x) { lock (mainlock) { File.AppendAllText("C:\\temp\\tlog.txt", DateTime.Now.ToString() + " - " + x.Replace('\0', '~') + "\r\n"); } }
+
+ public void ProcessRequest(HttpContext context)
+ {
+ var queryargs = System.Web.HttpUtility.ParseQueryString(context.Request.Url.Query);
+
+ if (!context.IsWebSocketRequest)
+ {
+ context.Response.StatusCode = 200;
+ context.Response.Redirect("default.htm");
+ context.Response.End();
+ return;
+ }
+
+ if (queryargs["host"] == null || queryargs["port"] == null || queryargs["tls"] == null)
+ {
+ context.Response.StatusCode = 200;
+ context.Response.ContentType = "text/plain";
+ context.Response.Write("Host, Port and Tls arguments expected.");
+ context.Response.End();
+ return;
+ }
+
+ host = queryargs["host"];
+ int.TryParse(queryargs["port"], out port);
+ tls = (queryargs["tls"] != null && string.Compare(queryargs["tls"], "1", true) == 0);
+
+ if (port < 1 || port > 65535)
+ {
+ context.Response.StatusCode = 200;
+ context.Response.ContentType = "text/plain";
+ context.Response.Write("Invalid port.");
+ context.Response.End();
+ return;
+ }
+
+ try
+ {
+ context.AcceptWebSocketRequest(ProcessNewWebSocket);
+ }
+ catch (Exception ex)
+ {
+ context.Response.StatusCode = 202;
+ context.Response.ContentType = "text/plain";
+ context.Response.Write("AcceptWebSocketRequest() Error: " + ex.ToString());
+ context.Response.End();
+ }
+ }
+
+ private bool CheckClientCert(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors errors)
+ {
+ return true;
+ }
+
+ private async Task ProcessNewWebSocket(AspNetWebSocketContext context)
+ {
+ websocket = context.WebSocket;
+ client = new TcpClient();
+ try { await client.ConnectAsync(host, port); } catch (Exception) { client = null; }
+
+ if (client == null)
+ {
+ await websocket.CloseAsync(WebSocketCloseStatus.EndpointUnavailable, "Unable to TCP connect to target host:port", CancellationToken.None);
+ websocket.Dispose();
+ websocket = null;
+ return;
+ }
+
+ try
+ {
+ if (tls == false)
+ {
+ stream = client.GetStream();
+ stream.BeginRead(clientReadBuf, 0, clientReadBuf.Length, new AsyncCallback(onClientReadData), null);
+ }
+ else
+ {
+ SslStream secureClientStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(CheckClientCert), null, EncryptionPolicy.RequireEncryption);
+ stream = secureClientStream;
+ secureClientStream.AuthenticateAsClientAsync(host).Wait();
+ stream.BeginRead(clientReadBuf, 0, clientReadBuf.Length, new AsyncCallback(onClientReadData), null);
+ }
+ }
+ catch (Exception) { closing = true; }
+
+ while (closing == false)
+ {
+ try
+ {
+ ArraySegment buffer = new ArraySegment(new byte[16384]);
+ WebSocketReceiveResult result = await websocket.ReceiveAsync(buffer, CancellationToken.None);
+ if (closing == true || websocket.State != WebSocketState.Open) break;
+ stream.WriteAsync(buffer.Array, buffer.Offset, result.Count).Wait();
+ }
+ catch (Exception) { }
+ }
+
+ try
+ {
+ await websocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Remote TCP connection closed", CancellationToken.None);
+ websocket.Dispose();
+ }
+ catch (Exception) { }
+
+ websocket = null;
+ stream = null;
+
+ try { client.Close(); } catch (Exception) { }
+ client = null;
+ }
+
+ private void onClientReadData(IAsyncResult ar)
+ {
+ int r = 0;
+ try { r = stream.EndRead(ar); } catch (Exception) { }
+
+ try
+ {
+ if (r == 0)
+ {
+ closing = true;
+ try { websocket.Abort(); } catch (Exception) { }
+ }
+ else
+ {
+ websocket.SendAsync(new ArraySegment(clientReadBuf, 0, r), WebSocketMessageType.Binary, true, CancellationToken.None).Wait();
+ stream.BeginRead(clientReadBuf, 0, clientReadBuf.Length, new AsyncCallback(onClientReadData), null);
+ }
+ }
+ catch (Exception) {
+ closing = true;
+ try { websocket.Abort(); } catch (Exception) { }
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/websitecompiler/Firmware-MeshCommander.wcc b/websitecompiler/Firmware-MeshCommander.wcc
new file mode 100644
index 0000000..3d53892
Binary files /dev/null and b/websitecompiler/Firmware-MeshCommander.wcc differ
diff --git a/websitecompiler/NodeWebkit-Commander.wcc b/websitecompiler/NodeWebkit-Commander.wcc
new file mode 100644
index 0000000..a07c8e3
Binary files /dev/null and b/websitecompiler/NodeWebkit-Commander.wcc differ
diff --git a/websocket-wrapper-0.2.0.js b/websocket-wrapper-0.2.0.js
new file mode 100644
index 0000000..d761c84
--- /dev/null
+++ b/websocket-wrapper-0.2.0.js
@@ -0,0 +1,206 @@
+/**
+* @description MeshCentral2 communication using websocket
+* @author Ylian Saint-Hilaire
+* @version v0.2.0a
+*/
+
+// Construct a MeshCentral2 communication object
+var CreateWebSocketWrapper = function (host, port, path, certhash) {
+ //console.log('CreateWebSocketWrapper', host, port, path, certhash);
+ var obj = {};
+ obj.host = host;
+ obj.port = port;
+ obj.path = path;
+ obj.certhash = certhash;
+ obj.socket = null;
+ obj.socketState = 0;
+ obj.net = require('net');
+ obj.tls = require('tls');
+ obj.crypto = require('crypto');
+ obj.constants = require('constants');
+ obj.xtlsoptions = null;
+ obj.accumulator = "";
+ obj.accopcodes = 0;
+ obj.acclen = -1;
+ obj.accmask = false;
+ obj.xtlsCertificate = null;
+ obj.xtlsFingerprint = null;
+
+ // Events
+ obj.ondata = null;
+ obj.onclose = null;
+ obj.ontimeout = null;
+ obj.onconnect = null;
+ obj.on = function (ev, fn) {
+ if (ev == 'data') { obj.ondata = fn; }
+ if (ev == 'close') { obj.onclose = fn; }
+ if (ev == 'error') { }
+ }
+
+ // Called to initiate a websocket connection to the server
+ obj.connect = function (onconnect) {
+ obj.onconnect = onconnect;
+ obj.socketState = 1;
+ obj.accumulator = "";
+ obj.accopcodes = 0;
+ obj.acclen = -1;
+ obj.accmask = false;
+ obj.xtlsFingerprint = null;
+ if (obj.certhash == null) {
+ //console.log('Connecting to ws://' + obj.host + ':' + obj.port + obj.path);
+ obj.socket = new obj.net.Socket();
+ obj.socket.setEncoding('binary');
+ obj.socket.connect(obj.port, obj.host, _OnSocketConnected);
+ } else {
+ //console.log('Connecting to wss://' + obj.host + ':' + obj.port + obj.path);
+ obj.socket = obj.tls.connect(obj.port, obj.host, { rejectUnauthorized: false }, _OnSocketConnected);
+ obj.socket.setEncoding('binary');
+ }
+ obj.socket.on('data', _OnSocketData);
+ obj.socket.on('close', _OnSocketClosed);
+ obj.socket.on('error', _OnSocketClosed);
+ }
+
+ obj.disconnect = function () { _OnSocketClosed("UserDisconnect"); }
+ obj.send = function (obj) { _Send(obj); }
+ obj.setEncoding = function(encoding) { }
+ obj.setTimeout = function (timeout) { }
+ obj.setNoDelay = function (delay) { }
+ obj.destroy = function () { _OnSocketClosed(); }
+ obj.end = function () { _OnSocketClosed(); }
+ obj.write = function (data) { _SendEx(data.toString('binary')); }
+
+ // Called when the socket is connected, we still need to do work to get the websocket connected
+ function _OnSocketConnected() {
+ if (obj.socket == null) return;
+ //console.log('Websocket connected');
+ // Check if this is really the MeshServer we want to connect to
+ obj.xtlsCertificate = obj.socket.getPeerCertificate();
+ obj.xtlsFingerprint = obj.xtlsCertificate.fingerprint.split(':').join('').toLowerCase();
+ if (obj.xtlsFingerprint != obj.certhash.split(':').join('').toLowerCase()) { console.error("Hash match fail", obj.xtlsFingerprint, obj.certhash.split(':').join('').toLowerCase()); _OnSocketClosed("HashMatchFail"); return; }
+
+ // Send the websocket switching header
+ obj.socket.write(new Buffer("GET " + obj.path + " HTTP/1.1\r\nHost: " + obj.host + "\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\n\r\n", "binary"));
+ }
+
+ // Called when socket data is received from the server
+ function _OnSocketData(e) {
+ //console.log('_OnSocketData', typeof e, e.length);
+ obj.accumulator += e;
+ if (obj.socketState == 1) {
+ // Look for the HTTP header response
+ var i = obj.accumulator.indexOf('\r\n\r\n');
+ if (i >= 0) {
+ var header = parseHttpHeader(obj.accumulator.substring(0, i));
+ if ((header != null) && (header._Path == '101')) {
+ // Success
+ obj.accumulator = obj.accumulator.substring(i + 4);
+ obj.socketState = 2;
+ //console.log('websocket connected');
+ if (obj.onconnect) { obj.onconnect(); }
+ } else {
+ // Fail
+ if (header == null) { _OnSocketClosed("Bad header"); } else { _OnSocketClosed(header._Path); }
+ }
+ }
+ }
+ if (obj.socketState >= 2) {
+ // Parse WebSocket data
+ //console.log('ACC(' + obj.accumulator.length + '):' + obj.accumulator);
+ while (_parseWsData() != 0) { }
+ }
+ };
+
+ // Parses websocket data from a socket connection, returns the number of bytes consumed.
+ function _parseWsData() {
+ if (obj.acclen == -1) {
+ // Look for a websocket header
+ if (obj.accumulator.length < 2) return 0;
+ var headsize = 2;
+ obj.accopcodes = obj.accumulator.charCodeAt(0);
+ obj.accmask = ((obj.accumulator.charCodeAt(1) & 0x80) != 0)
+ obj.acclen = (obj.accumulator.charCodeAt(1) & 0x7F);
+ if (obj.acclen == 126) {
+ if (obj.accumulator.length < 4) return 0;
+ headsize = 4;
+ obj.acclen = ReadShort(obj.accumulator, 2);
+ }
+ else if (obj.acclen == 127) {
+ if (obj.accumulator.length < 10) return 0;
+ headsize = 10;
+ obj.acclen = ReadInt(obj.accumulator, 6);
+ }
+ if (obj.accmask == true) {
+ // TODO: Do unmasking here.
+ headsize += 4;
+ }
+ //console.log('FIN: ' + ((obj.accopcodes & 0x80) != 0) + ', OP: ' + (obj.accopcodes & 0x0F) + ', LEN: ' + obj.acclen + ', MASK: ' + obj.accmask);
+ obj.accumulator = obj.accumulator.substring(headsize);
+ return headsize;
+ } else {
+ // Read the data
+ if (obj.accumulator.length < obj.acclen) return 0;
+ _OnWebSocketMessage(((obj.accopcodes & 0x80) != 0), (obj.accopcodes & 0x0F), obj.accumulator.substring(0, obj.acclen));
+ obj.accumulator = obj.accumulator.substring(obj.acclen);
+ var out = obj.acclen;
+ obj.acclen = -1;
+ return out;
+ }
+ }
+
+ // Called when the a command is received from the server
+ function _OnWebSocketMessage(fin, op, data) {
+ //console.log('FIN: ' + fin + ', OP: ' + op + ', LEN: ' + data.length, ': ' + data);
+ //if (op != 1) { return; } // We only process text frames
+ if ((op == 1 || op == 2) && (obj.ondata != null) && (data.length > 0)) { obj.ondata(data); } // Pass text & binary
+ if (op == 8) { _OnSocketClosed('RemoteClose'); } // Close the websocket
+ }
+
+ // Called when the socket is closed
+ function _OnSocketClosed(cause) {
+ //console.log('Websocket closed: ' + cause);
+ if (obj.socketState == 0) return;
+ obj.socketState = 0;
+ if (obj.onclose != null) { obj.onclose(); }
+ if (obj.socket != null) { try { obj.socket.end(); } catch (ex) { } obj.socket = null; }
+ }
+
+ // Called to send websocket data to the server
+ function _Send(object) {
+ if (obj.socketState < 2) { return; }
+ var data = new Buffer(JSON.stringify(object), "binary");
+ var header = String.fromCharCode(129); // 129 is default full fragment op code (129 = text, 130 = binary)
+ if (data.length < 126) { header += String.fromCharCode(data.length); }
+ else if (data.length < 65536) { header += String.fromCharCode(126) + ShortToStr(data.length); }
+ else { header += String.fromCharCode(127) + IntToStr(0) + IntToStr(data.length); }
+ try { obj.socket.write(new Buffer(header + data, 'binary')); } catch (e) { }
+ }
+
+ // Called to send websocket data to the server
+ function _SendEx(data) {
+ if (obj.socketState < 2) { return; }
+ //if (typeof data == 'string') { data = new Buffer(data, 'binary'); }
+ var header = String.fromCharCode(130); // 129 is default full fragment op code (129 = text, 130 = binary)
+ if (data.length < 126) { header += String.fromCharCode(data.length); }
+ else if (data.length < 65536) { header += String.fromCharCode(126) + ShortToStr(data.length); }
+ else { header += String.fromCharCode(127) + IntToStr(0) + IntToStr(data.length); }
+ try { obj.socket.write(new Buffer(header + data, 'binary')); } catch (e) { }
+ }
+
+ // Parse the data and return the decoded HTTP header if present.
+ function parseHttpHeader(data) {
+ var lines = data.split('\r\n');
+ if (lines.length < 1) return null;
+ var values = {}, directive = lines[0].split(' ');
+ if (directive.length < 3) return null;
+ values['_Action'] = directive[0];
+ values['_Path'] = directive[1];
+ values['_Protocol'] = directive[2];
+ for (i in lines) { if (i == 0) continue; var j = lines[i].indexOf(':'); if (j > 0) { values[lines[i].substring(0, j).trim()] = lines[i].substring(j + 1).trim(); } }
+ if (values['Content-Length']) { values['Content-Length'] = parseInt(values['Content-Length']); }
+ return values;
+ }
+
+ return obj;
+}
+
diff --git a/zlib-adler32.js b/zlib-adler32.js
new file mode 100644
index 0000000..d1165fa
--- /dev/null
+++ b/zlib-adler32.js
@@ -0,0 +1,279 @@
+/* zlib-adler32.js -- JavaScript implementation for the zlib adler32.
+ Version: 0.2.0
+ LastModified: Apr 12 2012
+ Copyright (C) 2012 Masanao Izumo
+
+ API documentation
+==============================================================================
+Usage: adler = ZLIB.adler32(adler, buf, offset, len);
+
+ Update a running Adler-32 checksum with the bytes buf[offset..offset+len-1] and
+ return the updated checksum. If buf is null, this function returns the
+ required initial value for the checksum.
+
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+ much faster.
+
+ Usage example:
+
+ var adler = ZLIB.adler32(0, null, 0, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = ZLIB.adler32(adler, buffer, 0, length);
+ }
+ if (adler != original_adler) error();
+
+==============================================================================
+Usage: adler = ZLIB.adler32_combine(adler1, adler2, len2);
+
+ Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
+ and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+ each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of
+ seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note
+ that the z_off_t type (like off_t) is a signed integer. If len2 is
+ negative, the result has no meaning or utility.
+*/
+
+if( typeof ZLIB === 'undefined' ) {
+ alert('ZLIB is not defined. SRC zlib.js before zlib-adler32.js')
+}
+
+(function() {
+
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-2011 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+var BASE = 65521; /* largest prime smaller than 65536 */
+var NMAX = 5552;
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+/* ========================================================================= */
+function adler32_string(adler, buf, offset, len)
+{
+ var sum2;
+ var n;
+
+ /* split Adler-32 into component sums */
+ sum2 = (adler >>> 16) & 0xffff;
+ adler &= 0xffff;
+
+ /* in case user likes doing a byte at a time, keep it fast */
+ if (len == 1) {
+ adler += buf.charCodeAt(offset) & 0xff;
+ if (adler >= BASE)
+ adler -= BASE;
+ sum2 += adler;
+ if (sum2 >= BASE)
+ sum2 -= BASE;
+ return adler | (sum2 << 16);
+ }
+
+ /* initial Adler-32 value (deferred check for len == 1 speed) */
+ if (buf === null)
+ return 1;
+
+ /* in case short lengths are provided, keep it somewhat fast */
+ if (len < 16) {
+ while (len--) {
+ adler += buf.charCodeAt(offset++) & 0xff;
+ sum2 += adler;
+ }
+ if (adler >= BASE)
+ adler -= BASE;
+ sum2 %= BASE; /* only added so many BASE's */
+ return adler | (sum2 << 16);
+ }
+
+ /* do length NMAX blocks -- requires just one modulo operation */
+ while (len >= NMAX) {
+ len -= NMAX;
+ n = NMAX >> 4; /* NMAX is divisible by 16 */
+ do {
+ /* 16 sums unrolled */
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ } while (--n);
+ adler %= BASE;
+ sum2 %= BASE;
+ }
+
+ /* do remaining bytes (less than NMAX, still just one modulo) */
+ if (len) { /* avoid modulos if none remaining */
+ while (len >= 16) {
+ len -= 16;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ }
+ while (len--) {
+ adler += buf.charCodeAt(offset++) & 0xff; sum2 += adler;
+ }
+ adler %= BASE;
+ sum2 %= BASE;
+ }
+
+ /* return recombined sums */
+ return adler | (sum2 << 16);
+}
+
+/* ========================================================================= */
+function adler32_array(adler, buf, offset, len)
+{
+ var sum2;
+ var n;
+
+ /* split Adler-32 into component sums */
+ sum2 = (adler >>> 16) & 0xffff;
+ adler &= 0xffff;
+
+ /* in case user likes doing a byte at a time, keep it fast */
+ if (len == 1) {
+ adler += buf[offset];
+ if (adler >= BASE)
+ adler -= BASE;
+ sum2 += adler;
+ if (sum2 >= BASE)
+ sum2 -= BASE;
+ return adler | (sum2 << 16);
+ }
+
+ /* initial Adler-32 value (deferred check for len == 1 speed) */
+ if (buf === null)
+ return 1;
+
+ /* in case short lengths are provided, keep it somewhat fast */
+ if (len < 16) {
+ while (len--) {
+ adler += buf[offset++];
+ sum2 += adler;
+ }
+ if (adler >= BASE)
+ adler -= BASE;
+ sum2 %= BASE; /* only added so many BASE's */
+ return adler | (sum2 << 16);
+ }
+
+ /* do length NMAX blocks -- requires just one modulo operation */
+ while (len >= NMAX) {
+ len -= NMAX;
+ n = NMAX >> 4; /* NMAX is divisible by 16 */
+ do {
+ /* 16 sums unrolled */
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ } while (--n);
+ adler %= BASE;
+ sum2 %= BASE;
+ }
+
+ /* do remaining bytes (less than NMAX, still just one modulo) */
+ if (len) { /* avoid modulos if none remaining */
+ while (len >= 16) {
+ len -= 16;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ adler += buf[offset++]; sum2 += adler;
+ }
+ while (len--) {
+ adler += buf[offset++]; sum2 += adler;
+ }
+ adler %= BASE;
+ sum2 %= BASE;
+ }
+
+ /* return recombined sums */
+ return adler | (sum2 << 16);
+}
+
+/* ========================================================================= */
+ZLIB.adler32 = function(adler, buf, offset, len)
+{
+ if(typeof buf === 'string') {
+ return adler32_string(adler, buf, offset, len);
+ } else {
+ return adler32_array(adler, buf, offset, len);
+ }
+};
+
+ZLIB.adler32_combine = function(adler1, adler2, len2)
+{
+ var sum1;
+ var sum2;
+ var rem;
+
+ /* for negative len, return invalid adler32 as a clue for debugging */
+ if (len2 < 0)
+ return 0xffffffff;
+
+ /* the derivation of this formula is left as an exercise for the reader */
+ len2 %= BASE; /* assumes len2 >= 0 */
+ rem = len2;
+ sum1 = adler1 & 0xffff;
+ sum2 = rem * sum1;
+ sum2 %= BASE;
+ sum1 += (adler2 & 0xffff) + BASE - 1;
+ sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
+ if (sum1 >= BASE) sum1 -= BASE;
+ if (sum1 >= BASE) sum1 -= BASE;
+ if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1);
+ if (sum2 >= BASE) sum2 -= BASE;
+ return sum1 | (sum2 << 16);
+}
+
+}());
diff --git a/zlib-crc32.js b/zlib-crc32.js
new file mode 100644
index 0000000..734bab6
--- /dev/null
+++ b/zlib-crc32.js
@@ -0,0 +1,246 @@
+/* zlib-adler32.js -- JavaScript implementation for the zlib crc32.
+ Version: 0.2.0
+ LastModified: Apr 12 2012
+ Copyright (C) 2012 Masanao Izumo
+
+ API documentation
+==============================================================================
+Usage: crc = ZLIB.crc32(crc, buf, offset, len);
+
+ Update a running CRC-32 with the bytes buf[offset..offset+len-1] and return the
+ updated CRC-32. If buf is null, this function returns the required
+ initial value for the for the crc. Pre- and post-conditioning (one's
+ complement) is performed within this function so it shouldn't be done by the
+ application.
+
+ Usage example:
+
+ var crc = ZLIB.crc32(0, null, 0, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ crc = ZLIB.crc32(crc, buffer, 0, length);
+ }
+ if (crc != original_crc) error();
+
+==============================================================================
+Usage: crc = crc32_combine(crc1, crc2, len2);
+
+ Combine two CRC-32 check values into one. For two sequences of bytes,
+ seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+ calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32
+ check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+ len2.
+*/
+
+if( typeof ZLIB === 'undefined' ) {
+ alert('ZLIB is not defined. SRC zlib.js before zlib-crc32.js')
+}
+
+(function() {
+
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-2006, 2010, 2011 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ *
+ * Thanks to Rodney Brown for his contribution of faster
+ * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
+ * tables for updating the shift register in one step with three exclusive-ors
+ * instead of four steps with four exclusive-ors. This results in about a
+ * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
+ */
+
+var crc_table = [
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+ 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+ 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+ 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+ 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+ 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+ 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+ 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+ 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+ 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+ 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+ 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+ 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+ 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+ 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+ 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+ 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+ 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+ 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+ 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+ 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+ 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+ 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+ 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+ 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+ 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+ 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+ 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+ 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+ 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+ 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+ 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+ 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+ 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+ 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+ 0x2d02ef8d ];
+
+/* ========================================================================= */
+function crc32_string(crc, buf, offset, len)
+{
+ if (buf == null) return 0;
+
+ crc = crc ^ 0xffffffff;
+ while (len >= 8) {
+ crc = crc_table[(crc ^ buf.charCodeAt(offset++)) & 0xff] ^ (crc >>> 8)
+ crc = crc_table[(crc ^ buf.charCodeAt(offset++)) & 0xff] ^ (crc >>> 8)
+ crc = crc_table[(crc ^ buf.charCodeAt(offset++)) & 0xff] ^ (crc >>> 8)
+ crc = crc_table[(crc ^ buf.charCodeAt(offset++)) & 0xff] ^ (crc >>> 8)
+ crc = crc_table[(crc ^ buf.charCodeAt(offset++)) & 0xff] ^ (crc >>> 8)
+ crc = crc_table[(crc ^ buf.charCodeAt(offset++)) & 0xff] ^ (crc >>> 8)
+ crc = crc_table[(crc ^ buf.charCodeAt(offset++)) & 0xff] ^ (crc >>> 8)
+ crc = crc_table[(crc ^ buf.charCodeAt(offset++)) & 0xff] ^ (crc >>> 8)
+ len -= 8;
+ }
+ if (len) do {
+ crc = crc_table[(crc ^ buf.charCodeAt(offset++)) & 0xff] ^ (crc >>> 8)
+ } while (--len);
+ return crc ^ 0xffffffff;
+}
+
+/* ========================================================================= */
+function crc32_array(crc, buf, offset, len)
+{
+ if (buf == null) return 0;
+
+ crc = crc ^ 0xffffffff;
+ while (len >= 8) {
+ crc = crc_table[(crc ^ buf[offset++]) & 0xff] ^ (crc >>> 8)
+ crc = crc_table[(crc ^ buf[offset++]) & 0xff] ^ (crc >>> 8)
+ crc = crc_table[(crc ^ buf[offset++]) & 0xff] ^ (crc >>> 8)
+ crc = crc_table[(crc ^ buf[offset++]) & 0xff] ^ (crc >>> 8)
+ crc = crc_table[(crc ^ buf[offset++]) & 0xff] ^ (crc >>> 8)
+ crc = crc_table[(crc ^ buf[offset++]) & 0xff] ^ (crc >>> 8)
+ crc = crc_table[(crc ^ buf[offset++]) & 0xff] ^ (crc >>> 8)
+ crc = crc_table[(crc ^ buf[offset++]) & 0xff] ^ (crc >>> 8)
+ len -= 8;
+ }
+ if (len) do {
+ crc = crc_table[(crc ^ buf[offset++]) & 0xff] ^ (crc >>> 8)
+ } while (--len);
+ return crc ^ 0xffffffff;
+}
+
+/* ========================================================================= */
+ZLIB.crc32 = function(crc, buf, offset, len)
+{
+ if(typeof buf === 'string') {
+ return crc32_string(crc, buf, offset, len);
+ } else {
+ return crc32_array(crc, buf, offset, len);
+ }
+};
+
+/* ========================================================================= */
+var GF2_DIM = 32; /* dimension of GF(2) vectors (length of CRC) */
+
+/* ========================================================================= */
+function gf2_matrix_times(mat, vec)
+{
+ var sum;
+ var mat_i = 0;
+
+ sum = 0;
+ while (vec) {
+ if (vec & 1)
+ sum ^= mat[mat_i];
+ vec >>= 1;
+ mat_i++;
+ }
+ return sum;
+}
+
+/* ========================================================================= */
+function gf2_matrix_square(square, mat)
+{
+ var n;
+
+ for (n = 0; n < GF2_DIM; n++)
+ square[n] = gf2_matrix_times(mat, mat[n]);
+}
+
+/* ========================================================================= */
+ZLIB.crc32_combine = function(crc1, crc2, len2)
+{
+ var n;
+ var row;
+ var even; /* even-power-of-two zeros operator */
+ var odd; /* odd-power-of-two zeros operator */
+
+ /* degenerate case (also disallow negative lengths) */
+ if (len2 <= 0)
+ return crc1;
+
+ even = new Array(GF2_DIM);
+ odd = new Array(GF2_DIM);
+
+ /* put operator for one zero bit in odd */
+ odd[0] = 0xedb88320; /* CRC-32 polynomial */
+ row = 1;
+ for (n = 1; n < GF2_DIM; n++) {
+ odd[n] = row;
+ row <<= 1;
+ }
+
+ /* put operator for two zero bits in even */
+ gf2_matrix_square(even, odd);
+
+ /* put operator for four zero bits in odd */
+ gf2_matrix_square(odd, even);
+
+ /* apply len2 zeros to crc1 (first square will put the operator for one
+ zero byte, eight zero bits, in even) */
+ do {
+ /* apply zeros operator for this bit of len2 */
+ gf2_matrix_square(even, odd);
+ if (len2 & 1)
+ crc1 = gf2_matrix_times(even, crc1);
+ len2 >>= 1;
+
+ /* if no more bits set, then done */
+ if (len2 == 0)
+ break;
+
+ /* another iteration of the loop with odd and even swapped */
+ gf2_matrix_square(odd, even);
+ if (len2 & 1)
+ crc1 = gf2_matrix_times(odd, crc1);
+ len2 >>= 1;
+
+ /* if no more bits set, then done */
+ } while (len2 != 0);
+
+ /* return combined crc */
+ crc1 ^= crc2;
+ return crc1;
+};
+
+}());
diff --git a/zlib-inflate.js b/zlib-inflate.js
new file mode 100644
index 0000000..bbe6ea2
--- /dev/null
+++ b/zlib-inflate.js
@@ -0,0 +1,1955 @@
+/* zlib-inflate.js -- JavaScript implementation for the zlib inflate.
+ Version: 0.2.0
+ LastModified: Apr 12 2012
+ Copyright (C) 2012 Masanao Izumo
+
+ This library is one of the JavaScript zlib implementation.
+ Some API's are modified from the original.
+ Only inflate API is implemented.
+
+ The original copyright notice (zlib 1.2.6):
+
+ Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
+ (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
+*/
+
+/*
+ API documentation
+==============================================================================
+Usage: z_stream = ZLIB.inflateInit([windowBits]);
+
+ Create the stream object for decompression.
+ See zlib.h for windowBits information.
+
+==============================================================================
+Usage: decoded_string = z_stream.inflate(encoded_string [, {OPTIONS...}]);
+
+OPTIONS:
+ next_in: decode start offset for encoded_string.
+
+ avail_in: // TODO document. See zlib.h for the information.
+
+ avail_out: // TODO document. See zlib.h for the information.
+
+ flush: // TODO document. See zlib.h for the information.
+
+Ex: decoded_string = z_stream.inflate(encoded_string);
+ decoded_string = z_stream.inflate(encoded_string,
+ {next_in: 0,
+ avail_in: encoded_string.length,
+ avail_out: 1024,
+ flush: ZLIB.Z_NO_FLUSH});
+
+ See zlib.h for more information.
+
+==============================================================================
+Usage: z_stream.inflateReset();
+ TODO document
+
+*/
+
+if( typeof ZLIB === 'undefined' ) {
+ alert('ZLIB is not defined. SRC zlib.js before zlib-inflate.js')
+}
+
+(function() {
+
+/* inflate.c -- zlib decompression
+ * Copyright (C) 1995-2011 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+var DEF_WBITS = 15;
+
+// inflate_mode
+var HEAD = 0; /* i: waiting for magic header */
+var FLAGS = 1; /* i: waiting for method and flags (gzip) */
+var TIME = 2; /* i: waiting for modification time (gzip) */
+var OS = 3; /* i: waiting for extra flags and operating system (gzip) */
+var EXLEN = 4; /* i: waiting for extra length (gzip) */
+var EXTRA = 5; /* i: waiting for extra bytes (gzip) */
+var NAME = 6; /* i: waiting for end of file name (gzip) */
+var COMMENT = 7; /* i: waiting for end of comment (gzip) */
+var HCRC = 8; /* i: waiting for header crc (gzip) */
+var DICTID = 9; /* i: waiting for dictionary check value */
+var DICT = 10; /* waiting for inflateSetDictionary() call */
+var TYPE = 11; /* i: waiting for type bits, including last-flag bit */
+var TYPEDO = 12; /* i: same, but skip check to exit inflate on new block */
+var STORED = 13; /* i: waiting for stored size (length and complement) */
+var COPY_ = 14; /* i/o: same as COPY below, but only first time in */
+var COPY = 15; /* i/o: waiting for input or output to copy stored block */
+var TABLE = 16; /* i: waiting for dynamic block table lengths */
+var LENLENS = 17; /* i: waiting for code length code lengths */
+var CODELENS = 18; /* i: waiting for length/lit and distance code lengths */
+var LEN_ = 19; /* i: same as LEN below, but only first time in */
+var LEN = 20; /* i: waiting for length/lit/eob code */
+var LENEXT = 21; /* i: waiting for length extra bits */
+var DIST = 22; /* i: waiting for distance code */
+var DISTEXT = 23; /* i: waiting for distance extra bits */
+var MATCH = 24; /* o: waiting for output space to copy string */
+var LIT = 25; /* o: waiting for output space to write literal */
+var CHECK = 26; /* i: waiting for 32-bit check value */
+var LENGTH = 27; /* i: waiting for 32-bit length (gzip) */
+var DONE = 28; /* finished check, done -- remain here until reset */
+var BAD = 29; /* got a data error -- remain here until reset */
+var MEM = 30; /* got an inflate() memory error -- remain here until reset */
+var SYNC = 31; /* looking for synchronization bytes to restart inflate() */
+
+/* Maximum size of the dynamic table. The maximum number of code structures is
+ 1444, which is the sum of 852 for literal/length codes and 592 for distance
+ codes. These values were found by exhaustive searches using the program
+ examples/enough.c found in the zlib distribtution. The arguments to that
+ program are the number of symbols, the initial root table size, and the
+ maximum bit length of a code. "enough 286 9 15" for literal/length codes
+ returns returns 852, and "enough 30 6 15" for distance codes returns 592.
+ The initial root table size (9 or 6) is found in the fifth argument of the
+ inflate_table() calls in inflate.c and infback.c. If the root table size is
+ changed, then these maximum sizes would be need to be recalculated and
+ updated. */
+var ENOUGH_LENS = 852;
+var ENOUGH_DISTS = 592;
+var ENOUGH = (ENOUGH_LENS + ENOUGH_DISTS);
+
+/* Type of code to build for inflate_table() */
+var CODES = 0;
+var LENS = 1;
+var DISTS = 2;
+
+
+
+var inflate_table_lbase = [ /* Length codes 257..285 base */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0];
+var inflate_table_lext = [ /* Length codes 257..285 extra */
+ 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
+ 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 203, 69];
+var inflate_table_dbase = [ /* Distance codes 0..29 base */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577, 0, 0];
+var inflate_table_dext = [ /* Distance codes 0..29 extra */
+ 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,
+ 23, 23, 24, 24, 25, 25, 26, 26, 27, 27,
+ 28, 28, 29, 29, 64, 64];
+
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-2012 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+ZLIB.inflate_copyright =
+ ' inflate 1.2.6 Copyright 1995-2012 Mark Adler ';
+/*
+ If you use the zlib library in a product, an acknowledgment is welcome
+ in the documentation of your product. If for some reason you cannot
+ include such an acknowledgment, I would appreciate that you keep this
+ copyright string in the executable of your product.
+ */
+
+/*
+ Build a set of tables to decode the provided canonical Huffman code.
+ The code lengths are lens[0..codes-1]. The result starts at *table,
+ whose indices are 0..2^bits-1. work is a writable array of at least
+ lens shorts, which is used as a work area. type is the type of code
+ to be generated, CODES, LENS, or DISTS. On return, zero is success,
+ -1 is an invalid code, and +1 means that ENOUGH isn't enough. table
+ on return points to the next available entry's address. bits is the
+ requested root table index bits, and on return it is the actual root
+ table index bits. It will differ if the request is greater than the
+ longest code or if it is less than the shortest code.
+*/
+function inflate_table(state, type)
+{
+ var MAXBITS = 15;
+ var table = state.next;
+ var bits = (type == DISTS ? state.distbits : state.lenbits);
+ var work = state.work;
+ var lens = state.lens;
+ var lens_offset = (type == DISTS ? state.nlen : 0);
+ var state_codes = state.codes;
+ var codes;
+ if(type == LENS)
+ codes = state.nlen;
+ else if(type == DISTS)
+ codes = state.ndist;
+ else // CODES
+ codes = 19;
+
+ var len; /* a code's length in bits */
+ var sym; /* index of code symbols */
+ var min, max; /* minimum and maximum code lengths */
+ var root; /* number of index bits for root table */
+ var curr; /* number of index bits for current table */
+ var drop; /* code bits to drop for sub-table */
+ var left; /* number of prefix codes available */
+ var used; /* code entries in table used */
+ var huff; /* Huffman code */
+ var incr; /* for incrementing code, index */
+ var fill; /* index for replicating entries */
+ var low; /* low bits for current root entry */
+ var mask; /* mask for low root bits */
+ var here; /* table entry for duplication */
+ var next; /* next available space in table */
+ var base; /* base value table to use */
+ var base_offset;
+ var extra; /* extra bits table to use */
+ var extra_offset;
+ var end; /* use base and extra for symbol > end */
+ var count = new Array(MAXBITS+1); /* number of codes of each length */
+ var offs = new Array(MAXBITS+1); /* offsets in table for each length */
+
+ /*
+ Process a set of code lengths to create a canonical Huffman code. The
+ code lengths are lens[0..codes-1]. Each length corresponds to the
+ symbols 0..codes-1. The Huffman code is generated by first sorting the
+ symbols by length from short to long, and retaining the symbol order
+ for codes with equal lengths. Then the code starts with all zero bits
+ for the first code of the shortest length, and the codes are integer
+ increments for the same length, and zeros are appended as the length
+ increases. For the deflate format, these bits are stored backwards
+ from their more natural integer increment ordering, and so when the
+ decoding tables are built in the large loop below, the integer codes
+ are incremented backwards.
+
+ This routine assumes, but does not check, that all of the entries in
+ lens[] are in the range 0..MAXBITS. The caller must assure this.
+ 1..MAXBITS is interpreted as that code length. zero means that that
+ symbol does not occur in this code.
+
+ The codes are sorted by computing a count of codes for each length,
+ creating from that a table of starting indices for each length in the
+ sorted table, and then entering the symbols in order in the sorted
+ table. The sorted table is work[], with that space being provided by
+ the caller.
+
+ The length counts are used for other purposes as well, i.e. finding
+ the minimum and maximum length codes, determining if there are any
+ codes at all, checking for a valid set of lengths, and looking ahead
+ at length counts to determine sub-table sizes when building the
+ decoding tables.
+ */
+
+ /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */
+ for (len = 0; len <= MAXBITS; len++)
+ count[len] = 0;
+ for (sym = 0; sym < codes; sym++)
+ count[lens[lens_offset + sym]]++;
+
+ /* bound code lengths, force root to be within code lengths */
+ root = bits;
+
+ for (max = MAXBITS; max >= 1; max--)
+ if (count[max] != 0) break;
+ if (root > max) root = max;
+ if (max == 0) {
+ /* no symbols to code at all */
+ /* invalid code marker */
+ here = {op:64, bits:1, val:0};
+ state_codes[table++] = here; /* make a table to force an error */
+ state_codes[table++] = here;
+ if(type == DISTS) state.distbits = 1; else state.lenbits = 1; // *bits = 1;
+ state.next = table;
+ return 0; /* no symbols, but wait for decoding to report error */
+ }
+ for (min = 1; min < max; min++)
+ if (count[min] != 0) break;
+ if (root < min) root = min;
+
+ /* check for an over-subscribed or incomplete set of lengths */
+ left = 1;
+ for (len = 1; len <= MAXBITS; len++) {
+ left <<= 1;
+ left -= count[len];
+ if (left < 0) return -1; /* over-subscribed */
+ }
+ if (left > 0 && (type == CODES || max != 1)) {
+ state.next = table;
+ return -1; /* incomplete set */
+ }
+
+ /* generate offsets into symbol table for each length for sorting */
+ offs[1] = 0;
+ for (len = 1; len < MAXBITS; len++)
+ offs[len + 1] = offs[len] + count[len];
+
+ /* sort symbols by length, by symbol order within each length */
+ for (sym = 0; sym < codes; sym++)
+ if (lens[lens_offset + sym] != 0) work[offs[lens[lens_offset + sym]]++] = sym;
+
+ /*
+ Create and fill in decoding tables. In this loop, the table being
+ filled is at next and has curr index bits. The code being used is huff
+ with length len. That code is converted to an index by dropping drop
+ bits off of the bottom. For codes where len is less than drop + curr,
+ those top drop + curr - len bits are incremented through all values to
+ fill the table with replicated entries.
+
+ root is the number of index bits for the root table. When len exceeds
+ root, sub-tables are created pointed to by the root entry with an index
+ of the low root bits of huff. This is saved in low to check for when a
+ new sub-table should be started. drop is zero when the root table is
+ being filled, and drop is root when sub-tables are being filled.
+
+ When a new sub-table is needed, it is necessary to look ahead in the
+ code lengths to determine what size sub-table is needed. The length
+ counts are used for this, and so count[] is decremented as codes are
+ entered in the tables.
+
+ used keeps track of how many table entries have been allocated from the
+ provided *table space. It is checked for LENS and DIST tables against
+ the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
+ the initial root table size constants. See the comments in inftrees.h
+ for more information.
+
+ sym increments through all symbols, and the loop terminates when
+ all codes of length max, i.e. all codes, have been processed. This
+ routine permits incomplete codes, so another loop after this one fills
+ in the rest of the decoding tables with invalid code markers.
+ */
+
+ /* set up for code type */
+ switch (type) {
+ case CODES:
+ base = extra = work; /* dummy value--not used */
+ base_offset = 0;
+ extra_offset = 0;
+ end = 19;
+ break;
+ case LENS:
+ base = inflate_table_lbase;
+ base_offset = -257; // base -= 257;
+ extra = inflate_table_lext;
+ extra_offset = -257; // extra -= 257;
+ end = 256;
+ break;
+ default: /* DISTS */
+ base = inflate_table_dbase;
+ extra = inflate_table_dext;
+ base_offset = 0;
+ extra_offset = 0;
+ end = -1;
+ }
+
+ /* initialize state for loop */
+ huff = 0; /* starting code */
+ sym = 0; /* starting code symbol */
+ len = min; /* starting code length */
+ next = table; /* current table to fill in */
+ curr = root; /* current table index bits */
+ drop = 0; /* current bits to drop from code for index */
+ low = -1; /* trigger new sub-table when len > root */
+ used = 1 << root; /* use root table entries */
+ mask = used - 1; /* mask for comparing low */
+
+ /* check available table space */
+ if ((type == LENS && used >= ENOUGH_LENS) ||
+ (type == DISTS && used >= ENOUGH_DISTS)) {
+ state.next = table;
+ return 1;
+ }
+
+ /* process all codes and make table entries */
+ for (;;) {
+ /* create table entry */
+ here = {op:0, bits:len - drop, val:0};
+ if (work[sym] < end) {
+ here.val = work[sym];
+ }
+ else if (work[sym] > end) {
+ here.op = extra[extra_offset + work[sym]];
+ here.val = base[base_offset + work[sym]];
+ }
+ else {
+ here.op = 32 + 64; /* end of block */
+ }
+
+ /* replicate for those indices with low len bits equal to huff */
+ incr = 1 << (len - drop);
+ fill = 1 << curr;
+ min = fill; /* save offset to next table */
+ do {
+ fill -= incr;
+ state_codes[next + (huff >>> drop) + fill] = here;
+ } while (fill != 0);
+
+ /* backwards increment the len-bit code huff */
+ incr = 1 << (len - 1);
+ while (huff & incr)
+ incr >>>= 1;
+ if (incr != 0) {
+ huff &= incr - 1;
+ huff += incr;
+ }
+ else
+ huff = 0;
+
+ /* go to next symbol, update count, len */
+ sym++;
+ if (--(count[len]) == 0) {
+ if (len == max) break;
+ len = lens[lens_offset + work[sym]];
+ }
+
+ /* create new sub-table if needed */
+ if (len > root && (huff & mask) != low) {
+ /* if first time, transition to sub-tables */
+ if (drop == 0)
+ drop = root;
+
+ /* increment past last table */
+ next += min; /* here min is 1 << curr */
+
+ /* determine length of next table */
+ curr = len - drop;
+ left = (1 << curr);
+ while (curr + drop < max) {
+ left -= count[curr + drop];
+ if (left <= 0) break;
+ curr++;
+ left <<= 1;
+ }
+
+ /* check for enough space */
+ used += 1 << curr;
+ if ((type == LENS && used >= ENOUGH_LENS) ||
+ (type == DISTS && used >= ENOUGH_DISTS)) {
+ state.next = table;
+ return 1;
+ }
+
+ /* point entry in root table to sub-table */
+ low = huff & mask;
+ state_codes[table + low] = {op:curr, bits:root, val:next - table};
+ }
+ }
+
+ /* fill in remaining table entry if code is incomplete (guaranteed to have
+ at most one remaining entry, since if the code is incomplete, the
+ maximum code length that was allowed to get this far is one bit) */
+ if (huff != 0) {
+ state_codes[next + huff] = {op:64, bits:len - drop, val:0};
+ }
+
+ /* set return parameters */
+ state.next = table + used;
+ if(type == DISTS) state.distbits = root; else state.lenbits = root; //*bits = root;
+ return 0;
+}
+
+/* inffast.c -- fast decoding
+ * Copyright (C) 1995-2008, 2010 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ Decode literal, length, and distance codes and write out the resulting
+ literal and match bytes until either not enough input or output is
+ available, an end-of-block is encountered, or a data error is encountered.
+ When large enough input and output buffers are supplied to inflate(), for
+ example, a 16K input buffer and a 64K output buffer, more than 95% of the
+ inflate execution time is spent in this routine.
+
+ Entry assumptions:
+
+ state->mode == LEN
+ strm->avail_in >= 6
+ strm->avail_out >= 258
+ start >= strm->avail_out
+ state->bits < 8
+
+ On return, state->mode is one of:
+
+ LEN -- ran out of enough output space or enough available input
+ TYPE -- reached end of block code, inflate() to interpret next block
+ BAD -- error in block data
+
+ Notes:
+
+ - The maximum input bits used by a length/distance pair is 15 bits for the
+ length code, 5 bits for the length extra, 15 bits for the distance code,
+ and 13 bits for the distance extra. This totals 48 bits, or six bytes.
+ Therefore if strm->avail_in >= 6, then there is enough input to avoid
+ checking for available input while decoding.
+
+ - The maximum bytes that a single length/distance pair can output is 258
+ bytes, which is the maximum length that can be coded. inflate_fast()
+ requires strm->avail_out >= 258 for each loop to avoid checking for
+ output space.
+ */
+function inflate_fast(strm,
+ start) /* inflate()'s starting value for strm->avail_out */
+{
+ var state;
+ var input_data; /* local strm->input_data */
+ var next_in; /* zlib.js: index of input_data */
+ var last; /* while next_in < last, enough input available */
+ var out; /* local strm.next_out */
+ var beg; /* inflate()'s initial strm.next_out */
+ var end; /* while out < end, enough space available */
+//NOSPRT #ifdef INFLATE_STRICT
+// unsigned dmax; /* maximum distance from zlib header */
+//#endif
+ var wsize; /* window size or zero if not using window */
+ var whave; /* valid bytes in the window */
+ var wnext; /* window write index */
+ var window; /* allocated sliding window, if wsize != 0 */
+ var hold; /* local strm->hold */
+ var bits; /* local strm->bits */
+ var codes; /* zlib.js: local state.codes */
+ var lcode; /* local strm->lencode */
+ var dcode; /* local strm->distcode */
+ var lmask; /* mask for first level of length codes */
+ var dmask; /* mask for first level of distance codes */
+ var here; /* retrieved table entry */
+ var op; /* code bits, operation, extra bits, or */
+ /* window position, window bytes to copy */
+ var len; /* match length, unused bytes */
+ var dist; /* match distance */
+ // var from; /* where to copy match from */
+ var from_window_offset = -1; /* index of window[] */
+ var from_out_offset = -1; /* index of next_out[] */
+
+ /* copy state to local variables */
+ state = strm.state;
+ input_data = strm.input_data;
+ next_in = strm.next_in;
+ last = next_in + strm.avail_in - 5;
+ out = strm.next_out;
+ beg = out - (start - strm.avail_out);
+ end = out + (strm.avail_out - 257);
+//NOSPRT #ifdef INFLATE_STRICT
+// dmax = state->dmax;
+//#endif
+ wsize = state.wsize;
+ whave = state.whave;
+ wnext = state.wnext;
+ window = state.window;
+ hold = state.hold;
+ bits = state.bits;
+ codes = state.codes;
+ lcode = state.lencode;
+ dcode = state.distcode;
+ lmask = (1 << state.lenbits) - 1;
+ dmask = (1 << state.distbits) - 1;
+
+ /* decode literals and length/distances until end-of-block or not enough
+ input data or output space */
+loop: do {
+ if (bits < 15) {
+ hold += (input_data.charCodeAt(next_in++) & 0xff) << bits;
+ bits += 8;
+ hold += (input_data.charCodeAt(next_in++) & 0xff) << bits;
+ bits += 8;
+ }
+ here = codes[lcode + (hold & lmask)];
+ dolen: while(true) {
+ op = here.bits;
+ hold >>>= op;
+ bits -= op;
+ op = here.op;
+ if (op == 0) { /* literal */
+// Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+// "inflate: literal '%c'\n" :
+// "inflate: literal 0x%02x\n", here.val));
+ strm.output_data += String.fromCharCode(here.val);
+ out++;
+ }
+ else if (op & 16) { /* length base */
+ len = here.val;
+ op &= 15; /* number of extra bits */
+ if (op) {
+ if (bits < op) {
+ hold += (input_data.charCodeAt(next_in++) & 0xff) << bits;
+ bits += 8;
+ }
+ len += hold & ((1 << op) - 1);
+ hold >>>= op;
+ bits -= op;
+ }
+// Tracevv((stderr, "inflate: length %u\n", len));
+ if (bits < 15) {
+ hold += (input_data.charCodeAt(next_in++) & 0xff) << bits;
+ bits += 8;
+ hold += (input_data.charCodeAt(next_in++) & 0xff) << bits;
+ bits += 8;
+ }
+ here = codes[dcode + (hold & dmask)];
+ dodist: while(true) {
+ op = here.bits;
+ hold >>>= op;
+ bits -= op;
+ op = here.op;
+ if (op & 16) { /* distance base */
+ dist = here.val;
+ op &= 15; /* number of extra bits */
+ if (bits < op) {
+ hold += (input_data.charCodeAt(next_in++) & 0xff) << bits;
+ bits += 8;
+ if (bits < op) {
+ hold += (input_data.charCodeAt(next_in++) & 0xff) << bits;
+ bits += 8;
+ }
+ }
+ dist += hold & ((1 << op) - 1);
+//NOSPRT #ifdef INFLATE_STRICT
+// if (dist > dmax) {
+// strm->msg = (char *)"invalid distance too far back";
+// state->mode = BAD;
+// break loop;
+// }
+//#endif
+ hold >>>= op;
+ bits -= op;
+// Tracevv((stderr, "inflate: distance %u\n", dist));
+ op = out - beg; /* max distance in output */
+ if (dist > op) { /* see if copy from window */
+ op = dist - op; /* distance back in window */
+ if (op > whave) {
+ if (state.sane) {
+ strm.msg = 'invalid distance too far back';
+ state.mode = BAD;
+ break loop;
+ }
+//NOSPRT #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+// if (len <= op - whave) {
+// do {
+// PUP(out) = 0;
+// } while (--len);
+// continue;
+// }
+// len -= op - whave;
+// do {
+// PUP(out) = 0;
+// } while (--op > whave);
+// if (op == 0) {
+// from = out - dist;
+// do {
+// PUP(out) = PUP(from);
+// } while (--len);
+// continue;
+// }
+//#endif
+ } // if (op > whave)
+
+ from_window_offset = 0;
+ from_out_offset = -1;
+ if (wnext == 0) { /* very common case */
+ from_window_offset += wsize - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ strm.output_data += window.substring(from_window_offset, from_window_offset + op);
+ out += op;
+ op = 0;
+ from_window_offset = -1;
+ from_out_offset = out - dist; /* rest from output */
+ }
+ }
+//NOTREACHED else if (wnext < op) { /* wrap around window */
+//NOTREACHED from += wsize + wnext - op;
+//NOTREACHED op -= wnext;
+//NOTREACHED if (op < len) { /* some from end of window */
+//NOTREACHED len -= op;
+//NOTREACHED do {
+//NOTREACHED PUP(out) = PUP(from);
+//NOTREACHED } while (--op);
+//NOTREACHED from = window - OFF;
+//NOTREACHED if (wnext < len) { /* some from start of window */
+//NOTREACHED op = wnext;
+//NOTREACHED len -= op;
+//NOTREACHED do {
+//NOTREACHED PUP(out) = PUP(from);
+//NOTREACHED } while (--op);
+//NOTREACHED from = out - dist; /* rest from output */
+//NOTREACHED }
+//NOTREACHED }
+//NOTREACHED }
+ else { /* contiguous in window */
+ from_window_offset += wnext - op;
+ if (op < len) { /* some from window */
+ len -= op;
+ strm.output_data += window.substring(from_window_offset, from_window_offset + op);
+ out += op;
+ from_window_offset = -1;
+ from_out_offset = out - dist; /* rest from output */
+ }
+ }
+ }
+ else {
+ from_window_offset = -1;
+ from_out_offset = out - dist; /* copy direct from output */
+ }
+
+ if (from_window_offset >= 0) {
+ strm.output_data += window.substring(from_window_offset, from_window_offset + len);
+ out += len;
+ from_window_offset += len;
+ } else {
+ var len_inner = len;
+ if(len_inner > out - from_out_offset)
+ len_inner = out - from_out_offset;
+ strm.output_data += strm.output_data.substring(
+ from_out_offset, from_out_offset + len_inner);
+ out += len_inner;
+ len -= len_inner;
+ from_out_offset += len_inner;
+ out += len;
+ while (len > 2) {
+ strm.output_data += strm.output_data.charAt(from_out_offset++);
+ strm.output_data += strm.output_data.charAt(from_out_offset++);
+ strm.output_data += strm.output_data.charAt(from_out_offset++);
+ len -= 3;
+ }
+ if (len) {
+ strm.output_data += strm.output_data.charAt(from_out_offset++);
+ if (len > 1)
+ strm.output_data += strm.output_data.charAt(from_out_offset++);
+ }
+ }
+ }
+ else if ((op & 64) == 0) { /* 2nd level distance code */
+ here = codes[dcode + (here.val + (hold & ((1 << op) - 1)))];
+ continue dodist; // goto dodist
+ }
+ else {
+ strm.msg = 'invalid distance code';
+ state.mode = BAD;
+ break loop;
+ }
+ break dodist; }
+ }
+ else if ((op & 64) == 0) { /* 2nd level length code */
+ here = codes[lcode + (here.val + (hold & ((1 << op) - 1)))];
+ continue dolen; // goto dolen;
+ }
+ else if (op & 32) { /* end-of-block */
+ // Tracevv((stderr, "inflate: end of block\n"));
+ state.mode = TYPE;
+ break loop;
+ }
+ else {
+ strm.msg = 'invalid literal/length code';
+ state.mode = BAD;
+ break loop;
+ }
+ break dolen; }
+ } while (next_in < last && out < end);
+
+ /* return unused bytes (on entry, bits < 8, so in won't go too far back) */
+ len = bits >>> 3;
+ next_in -= len;
+ bits -= len << 3;
+ hold &= (1 << bits) - 1;
+
+ /* update state and return */
+ strm.next_in = next_in;
+ strm.next_out = out;
+ strm.avail_in = (next_in < last ? 5 + (last - next_in) : 5 - (next_in - last));
+ strm.avail_out = (out < end ?
+ 257 + (end - out) : 257 - (out - end));
+ state.hold = hold;
+ state.bits = bits;
+}
+
+function new_array(size)
+{
+ var i;
+ var ary = new Array(size);
+ for(i = 0; i < size; i++)
+ ary[i] = 0;
+ return ary;
+}
+
+function getarg(opts, name, def_value)
+{
+ return (opts && (name in opts)) ? opts[name] : def_value;
+}
+
+function checksum_none()
+{
+ return 0;
+}
+
+/**
+ * z_stream constructor
+ * @constructor
+ */
+function inflate_state()
+{
+ var i;
+
+ this.mode = 0; /* current inflate mode */
+ this.last = 0; /* true if processing last block */
+ this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */
+ this.havedict = 0; /* true if dictionary provided */
+ this.flags = 0; /* gzip header method and flags (0 if zlib) */
+ this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */
+ this.check = 0; /* protected copy of check value */
+ this.total = 0; /* protected copy of output count */
+ this.head = null; /* where to save gzip header information */
+ /* sliding window */
+ this.wbits = 0; /* log base 2 of requested window size */
+ this.wsize = 0; /* window size or zero if not using window */
+ this.whave = 0; /* valid bytes in the window */
+ this.wnext = 0; /* window write index (TODO remove) */
+ this.window = null; /* allocated sliding window, if needed */
+ /* bit accumulator */
+ this.hold = 0; /* input bit accumulator */
+ this.bits = 0; /* number of bits in "in" */
+ /* for string and stored block copying */
+ this.length = 0; /* literal or length of data to copy */
+ this.offset = 0; /* distance back to copy string from */
+ /* for table and code decoding */
+ this.extra = 0; /* extra bits needed */
+ /* fixed and dynamic code tables */
+
+ /* zlib.js: modified implementation: lencode, distcode, next are offset of codes[] */
+ this.lencode = 0; /* starting table for length/literal codes */
+ this.distcode = 0; /* starting table for distance codes */
+ this.lenbits = 0; /* index bits for lencode */
+ this.distbits = 0; /* index bits for distcode */
+ /* dynamic table building */
+ this.ncode = 0; /* number of code length code lengths */
+ this.nlen = 0; /* number of length code lengths */
+ this.ndist = 0; /* number of distance code lengths */
+ this.have = 0; /* number of code lengths in lens[] */
+ this.next = 0; /* next available space in codes[] */
+ this.lens = new_array(320); /* temporary storage for code lengths */
+ this.work = new_array(288); /* work area for code table building */
+ this.codes = new Array(ENOUGH); /* space for code tables */
+ var c = {op:0, bits:0, val:0};
+ for(i = 0; i < ENOUGH; i++)
+ this.codes[i] = c;
+ this.sane = 0; /* if false, allow invalid distance too far */
+ this.back = 0; /* bits back of last unprocessed length/lit */
+ this.was = 0; /* initial length of match */
+}
+
+ZLIB.inflateResetKeep = function(strm)
+{
+ var state;
+
+ if (!strm || !strm.state) return ZLIB.Z_STREAM_ERROR;
+ state = strm.state;
+ strm.total_in = strm.total_out = state.total = 0;
+ strm.msg = null;
+ if (state.wrap) { /* to support ill-conceived Java test suite */
+ strm.adler = state.wrap & 1;
+ }
+
+ state.mode = HEAD;
+ state.last = 0;
+ state.havedict = 0;
+ state.dmax = 32768;
+ state.head = null;
+ state.hold = 0;
+ state.bits = 0;
+ state.lencode = 0;
+ state.distcode = 0;
+ state.next = 0;
+ state.sane = 1;
+ state.back = -1;
+ return ZLIB.Z_OK;
+};
+
+// Usage: strm = ZLIB.inflateReset(z_stream [, windowBits]);
+ZLIB.inflateReset = function(strm, windowBits)
+{
+ var wrap;
+ var state;
+
+ /* get the state */
+ if (!strm || !strm.state) return ZLIB.Z_STREAM_ERROR;
+ state = strm.state;
+
+ if(typeof windowBits === "undefined")
+ windowBits = DEF_WBITS;
+
+ /* extract wrap request from windowBits parameter */
+ if (windowBits < 0) {
+ wrap = 0;
+ windowBits = -windowBits;
+ }
+ else {
+ wrap = (windowBits >>> 4) + 1;
+ if (windowBits < 48)
+ windowBits &= 15;
+ }
+
+ if(wrap == 1 && (typeof ZLIB.adler32 === 'function')) {
+ strm.checksum_function = ZLIB.adler32;
+ } else if(wrap == 2 && (typeof ZLIB.crc32 === 'function')) {
+ strm.checksum_function = ZLIB.crc32;
+ } else {
+ strm.checksum_function = checksum_none;
+ }
+
+ /* set number of window bits, free window if different */
+ if (windowBits && (windowBits < 8 || windowBits > 15))
+ return ZLIB.Z_STREAM_ERROR;
+ if (state.window && state.wbits != windowBits) {
+ state.window = null;
+ }
+
+ /* update state and reset the rest of it */
+ state.wrap = wrap;
+ state.wbits = windowBits;
+ state.wsize = 0;
+ state.whave = 0;
+ state.wnext = 0;
+ return ZLIB.inflateResetKeep(strm);
+};
+
+// Usage: strm = ZLIB.inflateInit([windowBits]);
+ZLIB.inflateInit = function(windowBits)
+{
+ var strm = new ZLIB.z_stream();
+ strm.state = new inflate_state();
+ ZLIB.inflateReset(strm, windowBits);
+ return strm;
+};
+
+ZLIB.inflatePrime = function(strm, bits, value)
+{
+ var state;
+
+ if (!strm || !strm.state) return ZLIB.Z_STREAM_ERROR;
+ state = strm.state;
+ if (bits < 0) {
+ state.hold = 0;
+ state.bits = 0;
+ return ZLIB.Z_OK;
+ }
+ if (bits > 16 || state.bits + bits > 32) return ZLIB.Z_STREAM_ERROR;
+ value &= (1 << bits) - 1;
+ state.hold += value << state.bits;
+ state.bits += bits;
+ return ZLIB.Z_OK;
+};
+
+var lenfix_ary = null;
+var distfix_ary = null;
+
+function fixedtables(state)
+{
+ var i;
+ if (!lenfix_ary) lenfix_ary = [{ op: 96, bits: 7, val: 0 }, { op: 0, bits: 8, val: 80 }, { op: 0, bits: 8, val: 16 }, { op: 20, bits: 8, val: 115 }, { op: 18, bits: 7, val: 31 }, { op: 0, bits: 8, val: 112 }, { op: 0, bits: 8, val: 48 }, { op: 0, bits: 9, val: 192 }, { op: 16, bits: 7, val: 10 }, { op: 0, bits: 8, val: 96 }, { op: 0, bits: 8, val: 32 }, { op: 0, bits: 9, val: 160 }, { op: 0, bits: 8, val: 0 }, { op: 0, bits: 8, val: 128 }, { op: 0, bits: 8, val: 64 }, { op: 0, bits: 9, val: 224 }, { op: 16, bits: 7, val: 6 }, { op: 0, bits: 8, val: 88 }, { op: 0, bits: 8, val: 24 }, { op: 0, bits: 9, val: 144 }, { op: 19, bits: 7, val: 59 }, { op: 0, bits: 8, val: 120 }, { op: 0, bits: 8, val: 56 }, { op: 0, bits: 9, val: 208 }, { op: 17, bits: 7, val: 17 }, { op: 0, bits: 8, val: 104 }, { op: 0, bits: 8, val: 40 }, { op: 0, bits: 9, val: 176 }, { op: 0, bits: 8, val: 8 }, { op: 0, bits: 8, val: 136 }, { op: 0, bits: 8, val: 72 }, { op: 0, bits: 9, val: 240 }, { op: 16, bits: 7, val: 4 }, { op: 0, bits: 8, val: 84 }, { op: 0, bits: 8, val: 20 }, { op: 21, bits: 8, val: 227 }, { op: 19, bits: 7, val: 43 }, { op: 0, bits: 8, val: 116 }, { op: 0, bits: 8, val: 52 }, { op: 0, bits: 9, val: 200 }, { op: 17, bits: 7, val: 13 }, { op: 0, bits: 8, val: 100 }, { op: 0, bits: 8, val: 36 }, { op: 0, bits: 9, val: 168 }, { op: 0, bits: 8, val: 4 }, { op: 0, bits: 8, val: 132 }, { op: 0, bits: 8, val: 68 }, { op: 0, bits: 9, val: 232 }, { op: 16, bits: 7, val: 8 }, { op: 0, bits: 8, val: 92 }, { op: 0, bits: 8, val: 28 }, { op: 0, bits: 9, val: 152 }, { op: 20, bits: 7, val: 83 }, { op: 0, bits: 8, val: 124 }, { op: 0, bits: 8, val: 60 }, { op: 0, bits: 9, val: 216 }, { op: 18, bits: 7, val: 23 }, { op: 0, bits: 8, val: 108 }, { op: 0, bits: 8, val: 44 }, { op: 0, bits: 9, val: 184 }, { op: 0, bits: 8, val: 12 }, { op: 0, bits: 8, val: 140 }, { op: 0, bits: 8, val: 76 }, { op: 0, bits: 9, val: 248 }, { op: 16, bits: 7, val: 3 }, { op: 0, bits: 8, val: 82 }, { op: 0, bits: 8, val: 18 }, { op: 21, bits: 8, val: 163 }, { op: 19, bits: 7, val: 35 }, { op: 0, bits: 8, val: 114 }, { op: 0, bits: 8, val: 50 }, { op: 0, bits: 9, val: 196 }, { op: 17, bits: 7, val: 11 }, { op: 0, bits: 8, val: 98 }, { op: 0, bits: 8, val: 34 }, { op: 0, bits: 9, val: 164 }, { op: 0, bits: 8, val: 2 }, { op: 0, bits: 8, val: 130 }, { op: 0, bits: 8, val: 66 }, { op: 0, bits: 9, val: 228 }, { op: 16, bits: 7, val: 7 }, { op: 0, bits: 8, val: 90 }, { op: 0, bits: 8, val: 26 }, { op: 0, bits: 9, val: 148 }, { op: 20, bits: 7, val: 67 }, { op: 0, bits: 8, val: 122 }, { op: 0, bits: 8, val: 58 }, { op: 0, bits: 9, val: 212 }, { op: 18, bits: 7, val: 19 }, { op: 0, bits: 8, val: 106 }, { op: 0, bits: 8, val: 42 }, { op: 0, bits: 9, val: 180 }, { op: 0, bits: 8, val: 10 }, { op: 0, bits: 8, val: 138 }, { op: 0, bits: 8, val: 74 }, { op: 0, bits: 9, val: 244 }, { op: 16, bits: 7, val: 5 }, { op: 0, bits: 8, val: 86 }, { op: 0, bits: 8, val: 22 }, { op: 64, bits: 8, val: 0 }, { op: 19, bits: 7, val: 51 }, { op: 0, bits: 8, val: 118 }, { op: 0, bits: 8, val: 54 }, { op: 0, bits: 9, val: 204 }, { op: 17, bits: 7, val: 15 }, { op: 0, bits: 8, val: 102 }, { op: 0, bits: 8, val: 38 }, { op: 0, bits: 9, val: 172 }, { op: 0, bits: 8, val: 6 }, { op: 0, bits: 8, val: 134 }, { op: 0, bits: 8, val: 70 }, { op: 0, bits: 9, val: 236 }, { op: 16, bits: 7, val: 9 }, { op: 0, bits: 8, val: 94 }, { op: 0, bits: 8, val: 30 }, { op: 0, bits: 9, val: 156 }, { op: 20, bits: 7, val: 99 }, { op: 0, bits: 8, val: 126 }, { op: 0, bits: 8, val: 62 }, { op: 0, bits: 9, val: 220 }, { op: 18, bits: 7, val: 27 }, { op: 0, bits: 8, val: 110 }, { op: 0, bits: 8, val: 46 }, { op: 0, bits: 9, val: 188 }, { op: 0, bits: 8, val: 14 }, { op: 0, bits: 8, val: 142 }, { op: 0, bits: 8, val: 78 }, { op: 0, bits: 9, val: 252 }, { op: 96, bits: 7, val: 0 }, { op: 0, bits: 8, val: 81 }, { op: 0, bits: 8, val: 17 }, { op: 21, bits: 8, val: 131 }, { op: 18, bits: 7, val: 31 }, { op: 0, bits: 8, val: 113 }, { op: 0, bits: 8, val: 49 }, { op: 0, bits: 9, val: 194 }, { op: 16, bits: 7, val: 10 }, { op: 0, bits: 8, val: 97 }, { op: 0, bits: 8, val: 33 }, { op: 0, bits: 9, val: 162 }, { op: 0, bits: 8, val: 1 }, { op: 0, bits: 8, val: 129 }, { op: 0, bits: 8, val: 65 }, { op: 0, bits: 9, val: 226 }, { op: 16, bits: 7, val: 6 }, { op: 0, bits: 8, val: 89 }, { op: 0, bits: 8, val: 25 }, { op: 0, bits: 9, val: 146 }, { op: 19, bits: 7, val: 59 }, { op: 0, bits: 8, val: 121 }, { op: 0, bits: 8, val: 57 }, { op: 0, bits: 9, val: 210 }, { op: 17, bits: 7, val: 17 }, { op: 0, bits: 8, val: 105 }, { op: 0, bits: 8, val: 41 }, { op: 0, bits: 9, val: 178 }, { op: 0, bits: 8, val: 9 }, { op: 0, bits: 8, val: 137 }, { op: 0, bits: 8, val: 73 }, { op: 0, bits: 9, val: 242 }, { op: 16, bits: 7, val: 4 }, { op: 0, bits: 8, val: 85 }, { op: 0, bits: 8, val: 21 }, { op: 16, bits: 8, val: 258 }, { op: 19, bits: 7, val: 43 }, { op: 0, bits: 8, val: 117 }, { op: 0, bits: 8, val: 53 }, { op: 0, bits: 9, val: 202 }, { op: 17, bits: 7, val: 13 }, { op: 0, bits: 8, val: 101 }, { op: 0, bits: 8, val: 37 }, { op: 0, bits: 9, val: 170 }, { op: 0, bits: 8, val: 5 }, { op: 0, bits: 8, val: 133 }, { op: 0, bits: 8, val: 69 }, { op: 0, bits: 9, val: 234 }, { op: 16, bits: 7, val: 8 }, { op: 0, bits: 8, val: 93 }, { op: 0, bits: 8, val: 29 }, { op: 0, bits: 9, val: 154 }, { op: 20, bits: 7, val: 83 }, { op: 0, bits: 8, val: 125 }, { op: 0, bits: 8, val: 61 }, { op: 0, bits: 9, val: 218 }, { op: 18, bits: 7, val: 23 }, { op: 0, bits: 8, val: 109 }, { op: 0, bits: 8, val: 45 }, { op: 0, bits: 9, val: 186 }, { op: 0, bits: 8, val: 13 }, { op: 0, bits: 8, val: 141 }, { op: 0, bits: 8, val: 77 }, { op: 0, bits: 9, val: 250 }, { op: 16, bits: 7, val: 3 }, { op: 0, bits: 8, val: 83 }, { op: 0, bits: 8, val: 19 }, { op: 21, bits: 8, val: 195 }, { op: 19, bits: 7, val: 35 }, { op: 0, bits: 8, val: 115 }, { op: 0, bits: 8, val: 51 }, { op: 0, bits: 9, val: 198 }, { op: 17, bits: 7, val: 11 }, { op: 0, bits: 8, val: 99 }, { op: 0, bits: 8, val: 35 }, { op: 0, bits: 9, val: 166 }, { op: 0, bits: 8, val: 3 }, { op: 0, bits: 8, val: 131 }, { op: 0, bits: 8, val: 67 }, { op: 0, bits: 9, val: 230 }, { op: 16, bits: 7, val: 7 }, { op: 0, bits: 8, val: 91 }, { op: 0, bits: 8, val: 27 }, { op: 0, bits: 9, val: 150 }, { op: 20, bits: 7, val: 67 }, { op: 0, bits: 8, val: 123 }, { op: 0, bits: 8, val: 59 }, { op: 0, bits: 9, val: 214 }, { op: 18, bits: 7, val: 19 }, { op: 0, bits: 8, val: 107 }, { op: 0, bits: 8, val: 43 }, { op: 0, bits: 9, val: 182 }, { op: 0, bits: 8, val: 11 }, { op: 0, bits: 8, val: 139 }, { op: 0, bits: 8, val: 75 }, { op: 0, bits: 9, val: 246 }, { op: 16, bits: 7, val: 5 }, { op: 0, bits: 8, val: 87 }, { op: 0, bits: 8, val: 23 }, { op: 64, bits: 8, val: 0 }, { op: 19, bits: 7, val: 51 }, { op: 0, bits: 8, val: 119 }, { op: 0, bits: 8, val: 55 }, { op: 0, bits: 9, val: 206 }, { op: 17, bits: 7, val: 15 }, { op: 0, bits: 8, val: 103 }, { op: 0, bits: 8, val: 39 }, { op: 0, bits: 9, val: 174 }, { op: 0, bits: 8, val: 7 }, { op: 0, bits: 8, val: 135 }, { op: 0, bits: 8, val: 71 }, { op: 0, bits: 9, val: 238 }, { op: 16, bits: 7, val: 9 }, { op: 0, bits: 8, val: 95 }, { op: 0, bits: 8, val: 31 }, { op: 0, bits: 9, val: 158 }, { op: 20, bits: 7, val: 99 }, { op: 0, bits: 8, val: 127 }, { op: 0, bits: 8, val: 63 }, { op: 0, bits: 9, val: 222 }, { op: 18, bits: 7, val: 27 }, { op: 0, bits: 8, val: 111 }, { op: 0, bits: 8, val: 47 }, { op: 0, bits: 9, val: 190 }, { op: 0, bits: 8, val: 15 }, { op: 0, bits: 8, val: 143 }, { op: 0, bits: 8, val: 79 }, { op: 0, bits: 9, val: 254 }, { op: 96, bits: 7, val: 0 }, { op: 0, bits: 8, val: 80 }, { op: 0, bits: 8, val: 16 }, { op: 20, bits: 8, val: 115 }, { op: 18, bits: 7, val: 31 }, { op: 0, bits: 8, val: 112 }, { op: 0, bits: 8, val: 48 }, { op: 0, bits: 9, val: 193 }, { op: 16, bits: 7, val: 10 }, { op: 0, bits: 8, val: 96 }, { op: 0, bits: 8, val: 32 }, { op: 0, bits: 9, val: 161 }, { op: 0, bits: 8, val: 0 }, { op: 0, bits: 8, val: 128 }, { op: 0, bits: 8, val: 64 }, { op: 0, bits: 9, val: 225 }, { op: 16, bits: 7, val: 6 }, { op: 0, bits: 8, val: 88 }, { op: 0, bits: 8, val: 24 }, { op: 0, bits: 9, val: 145 }, { op: 19, bits: 7, val: 59 }, { op: 0, bits: 8, val: 120 }, { op: 0, bits: 8, val: 56 }, { op: 0, bits: 9, val: 209 }, { op: 17, bits: 7, val: 17 }, { op: 0, bits: 8, val: 104 }, { op: 0, bits: 8, val: 40 }, { op: 0, bits: 9, val: 177 }, { op: 0, bits: 8, val: 8 }, { op: 0, bits: 8, val: 136 }, { op: 0, bits: 8, val: 72 }, { op: 0, bits: 9, val: 241 }, { op: 16, bits: 7, val: 4 }, { op: 0, bits: 8, val: 84 }, { op: 0, bits: 8, val: 20 }, { op: 21, bits: 8, val: 227 }, { op: 19, bits: 7, val: 43 }, { op: 0, bits: 8, val: 116 }, { op: 0, bits: 8, val: 52 }, { op: 0, bits: 9, val: 201 }, { op: 17, bits: 7, val: 13 }, { op: 0, bits: 8, val: 100 }, { op: 0, bits: 8, val: 36 }, { op: 0, bits: 9, val: 169 }, { op: 0, bits: 8, val: 4 }, { op: 0, bits: 8, val: 132 }, { op: 0, bits: 8, val: 68 }, { op: 0, bits: 9, val: 233 }, { op: 16, bits: 7, val: 8 }, { op: 0, bits: 8, val: 92 }, { op: 0, bits: 8, val: 28 }, { op: 0, bits: 9, val: 153 }, { op: 20, bits: 7, val: 83 }, { op: 0, bits: 8, val: 124 }, { op: 0, bits: 8, val: 60 }, { op: 0, bits: 9, val: 217 }, { op: 18, bits: 7, val: 23 }, { op: 0, bits: 8, val: 108 }, { op: 0, bits: 8, val: 44 }, { op: 0, bits: 9, val: 185 }, { op: 0, bits: 8, val: 12 }, { op: 0, bits: 8, val: 140 }, { op: 0, bits: 8, val: 76 }, { op: 0, bits: 9, val: 249 }, { op: 16, bits: 7, val: 3 }, { op: 0, bits: 8, val: 82 }, { op: 0, bits: 8, val: 18 }, { op: 21, bits: 8, val: 163 }, { op: 19, bits: 7, val: 35 }, { op: 0, bits: 8, val: 114 }, { op: 0, bits: 8, val: 50 }, { op: 0, bits: 9, val: 197 }, { op: 17, bits: 7, val: 11 }, { op: 0, bits: 8, val: 98 }, { op: 0, bits: 8, val: 34 }, { op: 0, bits: 9, val: 165 }, { op: 0, bits: 8, val: 2 }, { op: 0, bits: 8, val: 130 }, { op: 0, bits: 8, val: 66 }, { op: 0, bits: 9, val: 229 }, { op: 16, bits: 7, val: 7 }, { op: 0, bits: 8, val: 90 }, { op: 0, bits: 8, val: 26 }, { op: 0, bits: 9, val: 149 }, { op: 20, bits: 7, val: 67 }, { op: 0, bits: 8, val: 122 }, { op: 0, bits: 8, val: 58 }, { op: 0, bits: 9, val: 213 }, { op: 18, bits: 7, val: 19 }, { op: 0, bits: 8, val: 106 }, { op: 0, bits: 8, val: 42 }, { op: 0, bits: 9, val: 181 }, { op: 0, bits: 8, val: 10 }, { op: 0, bits: 8, val: 138 }, { op: 0, bits: 8, val: 74 }, { op: 0, bits: 9, val: 245 }, { op: 16, bits: 7, val: 5 }, { op: 0, bits: 8, val: 86 }, { op: 0, bits: 8, val: 22 }, { op: 64, bits: 8, val: 0 }, { op: 19, bits: 7, val: 51 }, { op: 0, bits: 8, val: 118 }, { op: 0, bits: 8, val: 54 }, { op: 0, bits: 9, val: 205 }, { op: 17, bits: 7, val: 15 }, { op: 0, bits: 8, val: 102 }, { op: 0, bits: 8, val: 38 }, { op: 0, bits: 9, val: 173 }, { op: 0, bits: 8, val: 6 }, { op: 0, bits: 8, val: 134 }, { op: 0, bits: 8, val: 70 }, { op: 0, bits: 9, val: 237 }, { op: 16, bits: 7, val: 9 }, { op: 0, bits: 8, val: 94 }, { op: 0, bits: 8, val: 30 }, { op: 0, bits: 9, val: 157 }, { op: 20, bits: 7, val: 99 }, { op: 0, bits: 8, val: 126 }, { op: 0, bits: 8, val: 62 }, { op: 0, bits: 9, val: 221 }, { op: 18, bits: 7, val: 27 }, { op: 0, bits: 8, val: 110 }, { op: 0, bits: 8, val: 46 }, { op: 0, bits: 9, val: 189 }, { op: 0, bits: 8, val: 14 }, { op: 0, bits: 8, val: 142 }, { op: 0, bits: 8, val: 78 }, { op: 0, bits: 9, val: 253 }, { op: 96, bits: 7, val: 0 }, { op: 0, bits: 8, val: 81 }, { op: 0, bits: 8, val: 17 }, { op: 21, bits: 8, val: 131 }, { op: 18, bits: 7, val: 31 }, { op: 0, bits: 8, val: 113 }, { op: 0, bits: 8, val: 49 }, { op: 0, bits: 9, val: 195 }, { op: 16, bits: 7, val: 10 }, { op: 0, bits: 8, val: 97 }, { op: 0, bits: 8, val: 33 }, { op: 0, bits: 9, val: 163 }, { op: 0, bits: 8, val: 1 }, { op: 0, bits: 8, val: 129 }, { op: 0, bits: 8, val: 65 }, { op: 0, bits: 9, val: 227 }, { op: 16, bits: 7, val: 6 }, { op: 0, bits: 8, val: 89 }, { op: 0, bits: 8, val: 25 }, { op: 0, bits: 9, val: 147 }, { op: 19, bits: 7, val: 59 }, { op: 0, bits: 8, val: 121 }, { op: 0, bits: 8, val: 57 }, { op: 0, bits: 9, val: 211 }, { op: 17, bits: 7, val: 17 }, { op: 0, bits: 8, val: 105 }, { op: 0, bits: 8, val: 41 }, { op: 0, bits: 9, val: 179 }, { op: 0, bits: 8, val: 9 }, { op: 0, bits: 8, val: 137 }, { op: 0, bits: 8, val: 73 }, { op: 0, bits: 9, val: 243 }, { op: 16, bits: 7, val: 4 }, { op: 0, bits: 8, val: 85 }, { op: 0, bits: 8, val: 21 }, { op: 16, bits: 8, val: 258 }, { op: 19, bits: 7, val: 43 }, { op: 0, bits: 8, val: 117 }, { op: 0, bits: 8, val: 53 }, { op: 0, bits: 9, val: 203 }, { op: 17, bits: 7, val: 13 }, { op: 0, bits: 8, val: 101 }, { op: 0, bits: 8, val: 37 }, { op: 0, bits: 9, val: 171 }, { op: 0, bits: 8, val: 5 }, { op: 0, bits: 8, val: 133 }, { op: 0, bits: 8, val: 69 }, { op: 0, bits: 9, val: 235 }, { op: 16, bits: 7, val: 8 }, { op: 0, bits: 8, val: 93 }, { op: 0, bits: 8, val: 29 }, { op: 0, bits: 9, val: 155 }, { op: 20, bits: 7, val: 83 }, { op: 0, bits: 8, val: 125 }, { op: 0, bits: 8, val: 61 }, { op: 0, bits: 9, val: 219 }, { op: 18, bits: 7, val: 23 }, { op: 0, bits: 8, val: 109 }, { op: 0, bits: 8, val: 45 }, { op: 0, bits: 9, val: 187 }, { op: 0, bits: 8, val: 13 }, { op: 0, bits: 8, val: 141 }, { op: 0, bits: 8, val: 77 }, { op: 0, bits: 9, val: 251 }, { op: 16, bits: 7, val: 3 }, { op: 0, bits: 8, val: 83 }, { op: 0, bits: 8, val: 19 }, { op: 21, bits: 8, val: 195 }, { op: 19, bits: 7, val: 35 }, { op: 0, bits: 8, val: 115 }, { op: 0, bits: 8, val: 51 }, { op: 0, bits: 9, val: 199 }, { op: 17, bits: 7, val: 11 }, { op: 0, bits: 8, val: 99 }, { op: 0, bits: 8, val: 35 }, { op: 0, bits: 9, val: 167 }, { op: 0, bits: 8, val: 3 }, { op: 0, bits: 8, val: 131 }, { op: 0, bits: 8, val: 67 }, { op: 0, bits: 9, val: 231 }, { op: 16, bits: 7, val: 7 }, { op: 0, bits: 8, val: 91 }, { op: 0, bits: 8, val: 27 }, { op: 0, bits: 9, val: 151 }, { op: 20, bits: 7, val: 67 }, { op: 0, bits: 8, val: 123 }, { op: 0, bits: 8, val: 59 }, { op: 0, bits: 9, val: 215 }, { op: 18, bits: 7, val: 19 }, { op: 0, bits: 8, val: 107 }, { op: 0, bits: 8, val: 43 }, { op: 0, bits: 9, val: 183 }, { op: 0, bits: 8, val: 11 }, { op: 0, bits: 8, val: 139 }, { op: 0, bits: 8, val: 75 }, { op: 0, bits: 9, val: 247 }, { op: 16, bits: 7, val: 5 }, { op: 0, bits: 8, val: 87 }, { op: 0, bits: 8, val: 23 }, { op: 64, bits: 8, val: 0 }, { op: 19, bits: 7, val: 51 }, { op: 0, bits: 8, val: 119 }, { op: 0, bits: 8, val: 55 }, { op: 0, bits: 9, val: 207 }, { op: 17, bits: 7, val: 15 }, { op: 0, bits: 8, val: 103 }, { op: 0, bits: 8, val: 39 }, { op: 0, bits: 9, val: 175 }, { op: 0, bits: 8, val: 7 }, { op: 0, bits: 8, val: 135 }, { op: 0, bits: 8, val: 71 }, { op: 0, bits: 9, val: 239 }, { op: 16, bits: 7, val: 9 }, { op: 0, bits: 8, val: 95 }, { op: 0, bits: 8, val: 31 }, { op: 0, bits: 9, val: 159 }, { op: 20, bits: 7, val: 99 }, { op: 0, bits: 8, val: 127 }, { op: 0, bits: 8, val: 63 }, { op: 0, bits: 9, val: 223 }, { op: 18, bits: 7, val: 27 }, { op: 0, bits: 8, val: 111 }, { op: 0, bits: 8, val: 47 }, { op: 0, bits: 9, val: 191 }, { op: 0, bits: 8, val: 15 }, { op: 0, bits: 8, val: 143 }, { op: 0, bits: 8, val: 79 }, { op: 0, bits: 9, val: 255 }];
+ if (!distfix_ary) distfix_ary = [{ op: 16, bits: 5, val: 1 }, { op: 23, bits: 5, val: 257 }, { op: 19, bits: 5, val: 17 }, { op: 27, bits: 5, val: 4097 }, { op: 17, bits: 5, val: 5 }, { op: 25, bits: 5, val: 1025 }, { op: 21, bits: 5, val: 65 }, { op: 29, bits: 5, val: 16385 }, { op: 16, bits: 5, val: 3 }, { op: 24, bits: 5, val: 513 }, { op: 20, bits: 5, val: 33 }, { op: 28, bits: 5, val: 8193 }, { op: 18, bits: 5, val: 9 }, { op: 26, bits: 5, val: 2049 }, { op: 22, bits: 5, val: 129 }, { op: 64, bits: 5, val: 0 }, { op: 16, bits: 5, val: 2 }, { op: 23, bits: 5, val: 385 }, { op: 19, bits: 5, val: 25 }, { op: 27, bits: 5, val: 6145 }, { op: 17, bits: 5, val: 7 }, { op: 25, bits: 5, val: 1537 }, { op: 21, bits: 5, val: 97 }, { op: 29, bits: 5, val: 24577 }, { op: 16, bits: 5, val: 4 }, { op: 24, bits: 5, val: 769 }, { op: 20, bits: 5, val: 49 }, { op: 28, bits: 5, val: 12289 }, { op: 18, bits: 5, val: 13 }, { op: 26, bits: 5, val: 3073 }, { op: 22, bits: 5, val: 193 }, { op: 64, bits: 5, val: 0 }];
+ state.lencode = 0;
+ state.distcode = 512;
+ for(i = 0; i < 512; i++) {
+ state.codes[i] = lenfix_ary[i];
+ }
+ for(i = 0; i < 32; i++) {
+ state.codes[i + 512] = distfix_ary[i];
+ }
+ state.lenbits = 9;
+ state.distbits = 5;
+}
+
+/*
+ Update the window with the last wsize (normally 32K) bytes written before
+ returning. If window does not exist yet, create it. This is only called
+ when a window is already in use, or when output has been written during this
+ inflate call, but the end of the deflate stream has not been reached yet.
+ It is also called to create a window for dictionary data when a dictionary
+ is loaded.
+
+ Providing output buffers larger than 32K to inflate() should provide a speed
+ advantage, since only the last 32K of output is copied to the sliding window
+ upon return from inflate(), and since all distances after the first 32K of
+ output will fall in the output data, making match copies simpler and faster.
+ The advantage may be dependent on the size of the processor's data caches.
+*/
+function updatewindow(strm)
+{
+ var state = strm.state;
+ var out = strm.output_data.length;
+
+ /* if it hasn't been done already, allocate space for the window */
+ if (state.window === null) {
+ state.window = '';
+ }
+
+ /* if window not in use yet, initialize */
+ if (state.wsize == 0) {
+ state.wsize = 1 << state.wbits;
+ }
+
+ // zlib.js: Sliding window
+ if (out >= state.wsize) {
+ state.window = strm.output_data.substring(out - state.wsize);
+ } else {
+ if(state.whave + out < state.wsize) {
+ state.window += strm.output_data;
+ } else {
+ state.window = state.window.substring(state.whave - (state.wsize - out)) + strm.output_data;
+ }
+ }
+ state.whave = state.window.length;
+ if(state.whave < state.wsize) {
+ state.wnext = state.whave;
+ } else {
+ state.wnext = 0;
+ }
+ return 0;
+}
+
+
+// #ifdef GUNZIP
+function CRC2(strm, word)
+{
+ var hbuf = [word & 0xff, (word >>> 8) & 0xff];
+ strm.state.check = strm.checksum_function(strm.state.check, hbuf, 0, 2);
+}
+
+function CRC4(strm, word)
+{
+ var hbuf = [word & 0xff,
+ (word >>> 8) & 0xff,
+ (word >>> 16) & 0xff,
+ (word >>> 24) & 0xff];
+ strm.state.check = strm.checksum_function(strm.state.check, hbuf, 0, 4);
+}
+
+/* Load registers with state in inflate() for speed */
+function LOAD(strm, s)
+{
+ s.strm = strm; /* z_stream */
+ s.left = strm.avail_out; /* available output */
+ s.next = strm.next_in; /* next input */
+ s.have = strm.avail_in; /* available input */
+ s.hold = strm.state.hold; /* bit buffer */
+ s.bits = strm.state.bits; /* bits in bit buffer */
+ return s;
+}
+
+/* Restore state from registers in inflate() */
+function RESTORE(s)
+{
+ var strm = s.strm;
+ strm.next_in = s.next;
+ strm.avail_out = s.left;
+ strm.avail_in = s.have;
+ strm.state.hold = s.hold;
+ strm.state.bits = s.bits;
+}
+
+/* Clear the input bit accumulator */
+function INITBITS(s)
+{
+ s.hold = 0;
+ s.bits = 0;
+}
+
+/* Get a byte of input into the bit accumulator, or return from inflate()
+ if there is no input available. */
+function PULLBYTE(s)
+{
+ if (s.have == 0) return false;
+ s.have--;
+ s.hold += (s.strm.input_data.charCodeAt(s.next++) & 0xff) << s.bits;
+ s.bits += 8;
+ return true;
+}
+
+/* Assure that there are at least n bits in the bit accumulator. If there is
+ not enough available input to do that, then return from inflate(). */
+function NEEDBITS(s, n)
+{
+ // if(typeof n != 'number') throw 'ERROR';
+ while (s.bits < n) {
+ if(!PULLBYTE(s))
+ return false;
+ }
+ return true;
+}
+
+/* Return the low n bits of the bit accumulator (n < 16) */
+function BITS(s, n)
+{
+ return s.hold & ((1 << n) - 1);
+}
+
+/* Remove n bits from the bit accumulator */
+function DROPBITS(s, n)
+{
+ // if(typeof n != 'number') throw 'ERROR';
+ s.hold >>>= n;
+ s.bits -= n;
+}
+
+/* Remove zero to seven bits as needed to go to a byte boundary */
+function BYTEBITS(s)
+{
+ s.hold >>>= s.bits & 7;
+ s.bits -= s.bits & 7;
+}
+
+/* Reverse the bytes in a 32-bit value */
+function REVERSE(q)
+{
+ return ((q >>> 24) & 0xff) +
+ ((q >>> 8) & 0xff00) +
+ ((q & 0xff00) << 8) +
+ ((q & 0xff) << 24);
+}
+
+/*
+ inflate() uses a state machine to process as much input data and generate as
+ much output data as possible before returning. The state machine is
+ structured roughly as follows:
+
+ for (;;) switch (state) {
+ ...
+ case STATEn:
+ if (not enough input data or output space to make progress)
+ return;
+ ... make progress ...
+ state = STATEm;
+ break;
+ ...
+ }
+
+ so when inflate() is called again, the same case is attempted again, and
+ if the appropriate resources are provided, the machine proceeds to the
+ next state. The NEEDBITS() macro is usually the way the state evaluates
+ whether it can proceed or should return. NEEDBITS() does the return if
+ the requested bits are not available. The typical use of the BITS macros
+ is:
+
+ NEEDBITS(n);
+ ... do something with BITS(n) ...
+ DROPBITS(n);
+
+ where NEEDBITS(n) either returns from inflate() if there isn't enough
+ input left to load n bits into the accumulator, or it continues. BITS(n)
+ gives the low n bits in the accumulator. When done, DROPBITS(n) drops
+ the low n bits off the accumulator. INITBITS() clears the accumulator
+ and sets the number of available bits to zero. BYTEBITS() discards just
+ enough bits to put the accumulator on a byte boundary. After BYTEBITS()
+ and a NEEDBITS(8), then BITS(8) would return the next byte in the stream.
+
+ NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return
+ if there is no input available. The decoding of variable length codes uses
+ PULLBYTE() directly in order to pull just enough bytes to decode the next
+ code, and no more.
+
+ Some states loop until they get enough input, making sure that enough
+ state information is maintained to continue the loop where it left off
+ if NEEDBITS() returns in the loop. For example, want, need, and keep
+ would all have to actually be part of the saved state in case NEEDBITS()
+ returns:
+
+ case STATEw:
+ while (want < need) {
+ NEEDBITS(n);
+ keep[want++] = BITS(n);
+ DROPBITS(n);
+ }
+ state = STATEx;
+ case STATEx:
+
+ As shown above, if the next state is also the next case, then the break
+ is omitted.
+
+ A state may also return if there is not enough output space available to
+ complete that state. Those states are copying stored data, writing a
+ literal byte, and copying a matching string.
+
+ When returning, a "goto inf_leave" is used to update the total counters,
+ update the check value, and determine whether any progress has been made
+ during that inflate() call in order to return the proper return code.
+ Progress is defined as a change in either strm->avail_in or strm->avail_out.
+ When there is a window, goto inf_leave will update the window with the last
+ output written. If a goto inf_leave occurs in the middle of decompression
+ and there is no window currently, goto inf_leave will create one and copy
+ output to the window for the next call of inflate().
+
+ In this implementation, the flush parameter of inflate() only affects the
+ return code (per zlib.h). inflate() always writes as much as possible to
+ strm->next_out, given the space available and the provided input--the effect
+ documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers
+ the allocation of and copying into a sliding window until necessary, which
+ provides the effect documented in zlib.h for Z_FINISH when the entire input
+ stream available. So the only thing the flush parameter actually does is:
+ when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it
+ will return Z_BUF_ERROR if it has not reached the end of the stream.
+ */
+
+/* permutation of code lengths */
+var inflate_order = [
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15];
+ZLIB.inflate = function(strm, flush)
+{
+ var state;
+ var s;
+ var _in, out; /* save starting available input and output */
+ var copy; /* number of stored or match bytes to copy */
+ var from_window_offset = -1; /* index of window[] */
+ var from_out_offset = -1; /* index of next_out[] */
+ var here; /* current decoding table entry */
+ var last; /* parent table entry */
+ var len; /* length to copy for repeats, bits to drop */
+ var ret; /* return code */
+
+ if (!strm || !strm.state ||
+ (!strm.input_data && strm.avail_in != 0))
+ return ZLIB.Z_STREAM_ERROR;
+
+ state = strm.state;
+ if (state.mode == TYPE) state.mode = TYPEDO; /* skip check */
+
+ // LOAD
+ s = {};
+ LOAD(strm, s);
+
+ _in = s.have;
+ out = s.left;
+ ret = ZLIB.Z_OK;
+inf_leave: for (;;) {
+ switch (state.mode) {
+ case HEAD:
+ if (state.wrap == 0) {
+ state.mode = TYPEDO;
+ break;
+ }
+ if(!NEEDBITS(s, 16)) break inf_leave;
+// #ifdef GUNZIP
+ if ((state.wrap & 2) && s.hold == 0x8b1f) { /* gzip header */
+ state.check = strm.checksum_function(0, null, 0, 0);
+ CRC2(strm, s.hold);
+ INITBITS(s);
+ state.mode = FLAGS;
+ break;
+ }
+ state.flags = 0; /* expect zlib header */
+ if (state.head !== null)
+ state.head.done = -1;
+ if (!(state.wrap & 1) || /* check if zlib header allowed */
+//#else
+// if (
+//#endif
+ ((BITS(s, 8) << 8) + (s.hold >>> 8)) % 31) {
+ strm.msg = 'incorrect header check';
+ state.mode = BAD;
+ break;
+ }
+ if (BITS(s, 4) != ZLIB.Z_DEFLATED) {
+ strm.msg = 'unknown compression method';
+ state.mode = BAD;
+ break;
+ }
+
+ DROPBITS(s, 4);
+ len = BITS(s, 4) + 8;
+ if (state.wbits == 0)
+ state.wbits = len;
+ else if (len > state.wbits) {
+ strm.msg = 'invalid window size';
+ state.mode = BAD;
+ break;
+ }
+ state.dmax = 1 << len;
+// Tracev((stderr, "inflate: zlib header ok\n"));
+ strm.adler = state.check = strm.checksum_function(0, null, 0, 0);
+ state.mode = s.hold & 0x200 ? DICTID : TYPE;
+ INITBITS(s);
+ break;
+// #ifdef GUNZIP
+ case FLAGS:
+ if(!NEEDBITS(s, 16)) break inf_leave;
+ state.flags = s.hold;
+ if ((state.flags & 0xff) != ZLIB.Z_DEFLATED) {
+ strm.msg = "unknown compression method";
+ state.mode = BAD;
+ break;
+ }
+ if (state.flags & 0xe000) {
+ strm.msg = "unknown header flags set";
+ state.mode = BAD;
+ break;
+ }
+ if (state.head !== null)
+ state.head.text = (s.hold >>> 8) & 1;
+ if (state.flags & 0x0200) {
+ CRC2(strm, s.hold);
+ }
+ INITBITS(s);
+ state.mode = TIME;
+ case TIME:
+ if(!NEEDBITS(s, 32)) break inf_leave;
+ if (state.head !== null)
+ state.head.time = s.hold;
+ if (state.flags & 0x0200) {
+ CRC4(strm, s.hold);
+ }
+ INITBITS(s);
+ state.mode = OS;
+ case OS:
+ if(!NEEDBITS(s, 16)) break inf_leave;
+ if (state.head !== null) {
+ state.head.xflags = s.hold & 0xff;
+ state.head.os = s.hold >>> 8;
+ }
+ if (state.flags & 0x0200) {
+ CRC2(strm, s.hold);
+ }
+ INITBITS(s);
+ state.mode = EXLEN;
+ case EXLEN:
+ if (state.flags & 0x0400) {
+ if(!NEEDBITS(s, 16)) break inf_leave;
+ state.length = s.hold;
+ if (state.head !== null) {
+ state.head.extra_len = s.hold;
+ }
+ if (state.flags & 0x0200) {
+ CRC2(strm, s.hold);
+ }
+ INITBITS(s);
+ state.head.extra = "";
+ }
+ else if (state.head !== null) {
+ state.head.extra = null;
+ }
+ state.mode = EXTRA;
+ case EXTRA:
+ if (state.flags & 0x0400) {
+ copy = state.length;
+ if (copy > s.have) copy = s.have;
+ if (copy) {
+ if (state.head !== null &&
+ state.head.extra !== null) {
+ len = state.head.extra_len - state.length;
+/*
+ zmemcpy(state->head->extra + len, next,
+ len + copy > state->head->extra_max ?
+ state->head->extra_max - len : copy);
+*/
+ state.head.extra += strm.input_data.substring(
+ s.next, s.next + (len + copy > state.head.extra_max ?
+ state.head.extra_max - len : copy));
+
+ }
+ if (state.flags & 0x0200)
+ state.check = strm.checksum_function(state.check, strm.input_data, s.next, copy);
+ s.have -= copy;
+ s.next += copy;
+ state.length -= copy;
+ }
+ if (state.length) break inf_leave;
+ }
+ state.length = 0;
+ state.mode = NAME;
+ case NAME:
+ if (state.flags & 0x0800) {
+ if (s.have == 0) break inf_leave;
+ if (state.head !== null && state.head.name === null) {
+ state.head.name = "";
+ }
+ copy = 0;
+ // TODO end = strm.input_data.indexOf("\0", s.next);
+ // TODO state.length => state.head.name.length
+ do {
+ len = strm.input_data.charAt(s.next + copy); copy++;
+ if(len === "\0")
+ break;
+ if (state.head !== null &&
+ state.length < state.head.name_max) {
+ state.head.name += len;
+ state.length++;
+ }
+ } while (copy < s.have);
+ if (state.flags & 0x0200) {
+ state.check = strm.checksum_function(state.check, strm.input_data, s.next, copy);
+ }
+ s.have -= copy;
+ s.next += copy;
+ if (len !== "\0") break inf_leave;
+ }
+ else if (state.head !== null)
+ state.head.name = null;
+ state.length = 0;
+ state.mode = COMMENT;
+ case COMMENT:
+ if (state.flags & 0x1000) {
+ if (s.have == 0) break inf_leave;
+ copy = 0;
+ if (state.head !== null && state.head.comment === null) {
+ state.head.comment = "";
+ }
+ // TODO end = strm.input_data.indexOf("\0", s.next);
+ // TODO state.length => state.head.comment.length
+ do {
+ len = strm.input_data.charAt(s.next + copy); copy++;
+ if(len === "\0")
+ break;
+ if (state.head !== null &&
+ state.length < state.head.comm_max) {
+ state.head.comment += len;
+ state.length++;
+ }
+ } while (copy < s.have);
+ if (state.flags & 0x0200)
+ state.check = strm.checksum_function(state.check, strm.input_data, s.next, copy);
+ s.have -= copy;
+ s.next += copy;
+ if (len !== "\0") break inf_leave;
+ }
+ else if (state.head !== null)
+ state.head.comment = null;
+ state.mode = HCRC;
+ case HCRC:
+ if (state.flags & 0x0200) {
+ if(!NEEDBITS(s, 16)) break inf_leave;
+ if (s.hold != (state.check & 0xffff)) {
+ strm.msg = "header crc mismatch";
+ state.mode = BAD;
+ break;
+ }
+ INITBITS(s);
+ }
+ if (state.head !== null) {
+ state.head.hcrc = (state.flags >>> 9) & 1;
+ state.head.done = 1;
+ }
+ strm.adler = state.check = strm.checksum_function(0, null, 0, 0);
+ state.mode = TYPE;
+ break;
+//#endif
+ case DICTID:
+ if(!NEEDBITS(s, 32)) break inf_leave;
+ strm.adler = state.check = REVERSE(s.hold);
+ INITBITS(s);
+ state.mode = DICT;
+ case DICT:
+ if (state.havedict == 0) {
+ RESTORE(s);
+ return ZLIB.Z_NEED_DICT;
+ }
+ strm.adler = state.check = strm.checksum_function(0, null, 0, 0);
+ state.mode = TYPE;
+ case TYPE:
+ if (flush == ZLIB.Z_BLOCK || flush == ZLIB.Z_TREES) break inf_leave;
+ case TYPEDO:
+ if (state.last) {
+ BYTEBITS(s);
+ state.mode = CHECK;
+ break;
+ }
+ if(!NEEDBITS(s, 3)) break inf_leave;
+ state.last = BITS(s, 1);
+ DROPBITS(s, 1);
+ switch (BITS(s, 2)) {
+ case 0: /* stored block */
+// Tracev((stderr, "inflate: stored block%s\n",
+// state->last ? " (last)" : ""));
+ state.mode = STORED;
+ break;
+ case 1: /* fixed block */
+ fixedtables(state);
+// Tracev((stderr, "inflate: fixed codes block%s\n",
+// state->last ? " (last)" : ""));
+ state.mode = LEN_; /* decode codes */
+ if (flush == ZLIB.Z_TREES) {
+ DROPBITS(s, 2);
+ break inf_leave;
+ }
+ break;
+ case 2: /* dynamic block */
+// Tracev((stderr, "inflate: dynamic codes block%s\n",
+// state->last ? " (last)" : ""));
+ state.mode = TABLE;
+ break;
+ case 3:
+ strm.msg = 'invalid block type';
+ state.mode = BAD;
+ }
+ DROPBITS(s, 2);
+ break;
+ case STORED:
+ BYTEBITS(s); /* go to byte boundary */
+ if(!NEEDBITS(s, 32)) break inf_leave;
+ if ((s.hold & 0xffff) != (((s.hold >>> 16) & 0xffff) ^ 0xffff)) {
+ strm.msg = 'invalid stored block lengths';
+ state.mode = BAD;
+ break;
+ }
+ state.length = s.hold & 0xffff;
+// Tracev((stderr, "inflate: stored length %u\n",
+// state->length));
+ INITBITS(s);
+ state.mode = COPY_;
+ if (flush == ZLIB.Z_TREES) break inf_leave;
+ case COPY_:
+ state.mode = COPY;
+ case COPY:
+ copy = state.length;
+ if (copy) {
+ if (copy > s.have) copy = s.have;
+ if (copy > s.left) copy = s.left;
+ if (copy == 0) break inf_leave;
+ strm.output_data += strm.input_data.substring(s.next, s.next + copy);
+ strm.next_out += copy;
+ s.have -= copy;
+ s.next += copy;
+ s.left -= copy;
+ state.length -= copy;
+ break;
+ }
+// Tracev((stderr, "inflate: stored end\n"));
+ state.mode = TYPE;
+ break;
+ case TABLE:
+ if(!NEEDBITS(s, 14)) break inf_leave;
+ state.nlen = BITS(s, 5) + 257;
+ DROPBITS(s, 5);
+ state.ndist = BITS(s, 5) + 1;
+ DROPBITS(s, 5);
+ state.ncode = BITS(s, 4) + 4;
+ DROPBITS(s, 4);
+//#ifndef PKZIP_BUG_WORKAROUND
+ if (state.nlen > 286 || state.ndist > 30) {
+ strm.msg = 'too many length or distance symbols';
+ state.mode = BAD;
+ break;
+ }
+//#endif
+// Tracev((stderr, "inflate: table sizes ok\n"));
+ state.have = 0;
+ state.mode = LENLENS;
+ case LENLENS:
+ while (state.have < state.ncode) {
+ if(!NEEDBITS(s, 3)) break inf_leave;
+ var tmp = BITS(s, 3);
+ state.lens[inflate_order[state.have++]] = tmp;
+ DROPBITS(s, 3);
+ }
+ while (state.have < 19)
+ state.lens[inflate_order[state.have++]] = 0;
+ state.next = 0;
+ state.lencode = 0;
+ state.lenbits = 7;
+
+// ret = inflate_table(CODES, state->lens, 19, &(state->next),
+// &(state->lenbits), state->work);
+ ret = inflate_table(state, CODES);
+
+ if (ret) {
+ strm.msg = 'invalid code lengths set';
+ state.mode = BAD;
+ break;
+ }
+// Tracev((stderr, "inflate: code lengths ok\n"));
+ state.have = 0;
+ state.mode = CODELENS;
+ case CODELENS:
+ while (state.have < state.nlen + state.ndist) {
+ for (;;) {
+ here = state.codes[state.lencode + BITS(s, state.lenbits)];
+ if (here.bits <= s.bits) break;
+ if(!PULLBYTE(s)) break inf_leave;
+ }
+ if (here.val < 16) {
+ DROPBITS(s, here.bits);
+ state.lens[state.have++] = here.val;
+ }
+ else {
+ if (here.val == 16) {
+ if(!NEEDBITS(s, here.bits + 2)) break inf_leave;
+ DROPBITS(s, here.bits);
+ if (state.have == 0) {
+ strm.msg = 'invalid bit length repeat';
+ state.mode = BAD;
+ break;
+ }
+ len = state.lens[state.have - 1];
+ copy = 3 + BITS(s, 2);
+ DROPBITS(s, 2);
+ }
+ else if (here.val == 17) {
+ if(!NEEDBITS(s, here.bits + 3)) break inf_leave;
+ DROPBITS(s, here.bits);
+ len = 0;
+ copy = 3 + BITS(s, 3);
+ DROPBITS(s, 3);
+ }
+ else {
+ if(!NEEDBITS(s, here.bits + 7)) break inf_leave;
+ DROPBITS(s, here.bits);
+ len = 0;
+ copy = 11 + BITS(s, 7);
+ DROPBITS(s, 7);
+ }
+ if (state.have + copy > state.nlen + state.ndist) {
+ strm.msg = 'invalid bit length repeat';
+ state.mode = BAD;
+ break;
+ }
+ while (copy--)
+ state.lens[state.have++] = len;
+ }
+ }
+
+ /* handle error breaks in while */
+ if (state.mode == BAD) break;
+
+ /* check for end-of-block code (better have one) */
+ if (state.lens[256] == 0) {
+ strm.msg = 'invalid code -- missing end-of-block';
+ state.mode = BAD;
+ break;
+ }
+
+ /* build code tables -- note: do not change the lenbits or distbits
+ values here (9 and 6) without reading the comments in inftrees.h
+ concerning the ENOUGH constants, which depend on those values */
+ state.next = 0;
+ state.lencode = state.next;
+ state.lenbits = 9;
+// ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
+// &(state->lenbits), state->work);
+ ret = inflate_table(state, LENS);
+ if (ret) {
+ strm.msg = 'invalid literal/lengths set';
+ state.mode = BAD;
+ break;
+ }
+ state.distcode = state.next;
+ state.distbits = 6;
+// ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next),
+// &(state->distbits), state->work);
+ ret = inflate_table(state, DISTS);
+ if (ret) {
+ strm.msg = 'invalid distances set';
+ state.mode = BAD;
+ break;
+ }
+// Tracev((stderr, "inflate: codes ok\n"));
+ state.mode = LEN_;
+ if (flush == ZLIB.Z_TREES) break inf_leave;
+ case LEN_:
+ state.mode = LEN;
+ case LEN:
+ if (s.have >= 6 && s.left >= 258) {
+ RESTORE(s);
+ inflate_fast(strm, out);
+ LOAD(strm, s);
+ if (state.mode == TYPE)
+ state.back = -1;
+ break;
+ }
+ state.back = 0;
+ for (;;) {
+ here = state.codes[state.lencode + BITS(s, state.lenbits)];
+ if (here.bits <= s.bits) break;
+ if(!PULLBYTE(s)) break inf_leave;
+ }
+ if (here.op && (here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state.codes[state.lencode + last.val +
+ (BITS(s, last.bits + last.op) >>> last.bits)];
+ if (last.bits + here.bits <= s.bits) break;
+ if(!PULLBYTE(s)) break inf_leave;
+ }
+ DROPBITS(s, last.bits);
+ state.back += last.bits;
+ }
+ DROPBITS(s, here.bits);
+ state.back += here.bits;
+ state.length = here.val;
+ if (here.op == 0) {
+// Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
+// "inflate: literal '%c'\n" :
+// "inflate: literal 0x%02x\n", here.val));
+ state.mode = LIT;
+ break;
+ }
+ if (here.op & 32) {
+// Tracevv((stderr, "inflate: end of block\n"));
+ state.back = -1;
+ state.mode = TYPE;
+ break;
+ }
+ if (here.op & 64) {
+ strm.msg = 'invalid literal/length code';
+ state.mode = BAD;
+ break;
+ }
+ state.extra = here.op & 15;
+ state.mode = LENEXT;
+ case LENEXT:
+ if (state.extra) {
+ if(!NEEDBITS(s, state.extra)) break inf_leave;
+ state.length += BITS(s, state.extra);
+ DROPBITS(s, state.extra);
+ state.back += state.extra;
+ }
+ //Tracevv((stderr, "inflate: length %u\n", state->length));
+ state.was = state.length;
+ state.mode = DIST;
+ case DIST:
+ for (;;) {
+ here = state.codes[state.distcode + BITS(s, state.distbits)];
+ if (here.bits <= s.bits) break;
+ if(!PULLBYTE(s)) break inf_leave;
+ }
+ if ((here.op & 0xf0) == 0) {
+ last = here;
+ for (;;) {
+ here = state.codes[state.distcode + last.val +
+ (BITS(s, last.bits + last.op) >>> last.bits)];
+ if ((last.bits + here.bits) <= s.bits) break;
+ if(!PULLBYTE(s)) break inf_leave;
+ }
+ DROPBITS(s, last.bits);
+ state.back += last.bits;
+ }
+ DROPBITS(s, here.bits);
+ state.back += here.bits;
+ if (here.op & 64) {
+ strm.msg = 'invalid distance code';
+ state.mode = BAD;
+ break;
+ }
+ state.offset = here.val;
+ state.extra = here.op & 15;
+ state.mode = DISTEXT;
+ case DISTEXT:
+ if (state.extra) {
+ if(!NEEDBITS(s, state.extra)) break inf_leave;
+ state.offset += BITS(s, state.extra);
+ DROPBITS(s, state.extra);
+ state.back += state.extra;
+ }
+//NOSPRT #ifdef INFLATE_STRICT
+// if (state->offset > state->dmax) {
+// strm->msg = (char *)"invalid distance too far back";
+// state->mode = BAD;
+// break;
+// }
+//#endif
+// Tracevv((stderr, "inflate: distance %u\n", state->offset));
+ state.mode = MATCH;
+ case MATCH:
+ if (s.left == 0) break inf_leave;
+ copy = out - s.left;
+ if (state.offset > copy) { /* copy from window */
+ copy = state.offset - copy;
+ if (copy > state.whave) {
+ if (state.sane) {
+ strm.msg = 'invalid distance too far back';
+ state.mode = BAD;
+ break;
+ }
+//NOSPRT #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
+// Trace((stderr, "inflate.c too far\n"));
+// copy -= state->whave;
+// if (copy > state->length) copy = state->length;
+// if (copy > left) copy = left;
+// left -= copy;
+// state->length -= copy;
+// do {
+// *put++ = 0;
+// } while (--copy);
+// if (state->length == 0) state->mode = LEN;
+// break;
+//#endif
+ }
+ if (copy > state.wnext) {
+ copy -= state.wnext;
+ // from = state->window + (state->wsize - copy);
+ from_window_offset = state.wsize - copy;
+ from_out_offset = -1;
+ }
+ else {
+ // from = state->window + (state->wnext - copy);
+ from_window_offset = state.wnext - copy;
+ from_out_offset = -1;
+ }
+ if (copy > state.length) copy = state.length;
+ }
+ else { /* copy from output */
+ // from = put - state->offset;
+ from_window_offset = -1;
+ from_out_offset = strm.next_out - state.offset;
+ copy = state.length;
+ }
+ if (copy > s.left) copy = s.left;
+ s.left -= copy;
+ state.length -= copy;
+ if( from_window_offset >= 0 ) {
+ strm.output_data += state.window.substring(from_window_offset, from_window_offset + copy);
+ strm.next_out += copy;
+ copy = 0;
+ } else {
+ strm.next_out += copy;
+ do {
+ strm.output_data += strm.output_data.charAt(from_out_offset++);
+ } while (--copy);
+ }
+ if (state.length == 0) state.mode = LEN;
+ break;
+ case LIT:
+ if (s.left == 0) break inf_leave;
+
+ strm.output_data += String.fromCharCode(state.length);
+ strm.next_out++;
+ //*put++ = (unsigned char)(state->length);
+
+ s.left--;
+ state.mode = LEN;
+ break;
+ case CHECK:
+ if (state.wrap) {
+ if(!NEEDBITS(s, 32)) break inf_leave;
+ out -= s.left;
+ strm.total_out += out;
+ state.total += out;
+ if (out)
+ strm.adler = state.check =
+ strm.checksum_function(state.check, strm.output_data, strm.output_data.length - out, out);
+ out = s.left;
+ if ((
+// #ifdef GUNZIP
+ state.flags ? s.hold :
+//#endif
+ REVERSE(s.hold)) != state.check) {
+ strm.msg = "incorrect data check";
+ state.mode = BAD;
+ break;
+ }
+ INITBITS(s);
+//debug("## inflate: check matches trailer\n");
+// Tracev((stderr, "inflate: check matches trailer\n"));
+ }
+//#ifdef GUNZIP
+ state.mode = LENGTH;
+ case LENGTH:
+ if (state.wrap && state.flags) {
+ if(!NEEDBITS(s, 32)) break inf_leave;
+ if (s.hold != (state.total & 0xffffffff)) {
+ strm.msg = 'incorrect length check';
+ state.mode = BAD;
+ break;
+ }
+ INITBITS(s);
+ //Tracev((stderr, "inflate: length matches trailer\n"));
+ }
+//#endif
+ state.mode = DONE;
+ case DONE:
+ ret = ZLIB.Z_STREAM_END;
+ break inf_leave;
+ case BAD:
+ ret = ZLIB.Z_DATA_ERROR;
+ break inf_leave;
+ case MEM:
+ return ZLIB.Z_MEM_ERROR;
+ case SYNC:
+ default:
+ return ZLIB.Z_STREAM_ERROR;
+ } }
+
+ /*
+ Return from inflate(), updating the total counts and the check value.
+ If there was no progress during the inflate() call, return a buffer
+ error. Call updatewindow() to create and/or update the window state.
+ Note: a memory error from inflate() is non-recoverable.
+ */
+inf_leave:
+ RESTORE(s);
+ if (state.wsize || (out != strm.avail_out && state.mode < BAD &&
+ (state.mode < CHECK || flush != ZLIB.Z_FINISH)))
+ if (updatewindow(strm)) {
+ state.mode = MEM;
+ return ZLIB.Z_MEM_ERROR;
+ }
+ _in -= strm.avail_in;
+ out -= strm.avail_out;
+ strm.total_in += _in;
+ strm.total_out += out;
+ state.total += out;
+ if (state.wrap && out)
+ strm.adler = state.check = strm.checksum_function(state.check, strm.output_data, 0, strm.output_data.length);
+ strm.data_type = state.bits + (state.last ? 64 : 0) +
+ (state.mode == TYPE ? 128 : 0) +
+ (state.mode == LEN_ || state.mode == COPY_ ? 256 : 0);
+ if (((_in == 0 && out == 0) || flush == ZLIB.Z_FINISH) && ret == ZLIB.Z_OK)
+ ret = ZLIB.Z_BUF_ERROR;
+ return ret;
+};
+
+ZLIB.inflateEnd = function(strm)
+{
+ var state;
+ if (!strm || !strm.state )
+ return ZLIB.Z_STREAM_ERROR;
+ state = strm.state;
+ state.window = null;
+ strm.state = null;
+ // Tracev((stderr, "inflate: end\n"));
+ return ZLIB.Z_OK;
+};
+
+ZLIB.z_stream.prototype.inflate = function(input_string, opts)
+{
+ var flush;
+ var avail_out;
+ var DEFAULT_BUFFER_SIZE = 16384;
+
+ this.input_data = input_string;
+ this.next_in = getarg(opts, 'next_in', 0);
+ this.avail_in = getarg(opts, 'avail_in', input_string.length - this.next_in);
+
+ flush = getarg(opts, 'flush', ZLIB.Z_SYNC_FLUSH);
+ avail_out = getarg(opts, 'avail_out', -1);
+
+ var result = '';
+ do {
+ this.avail_out = (avail_out >= 0 ? avail_out : DEFAULT_BUFFER_SIZE);
+ this.output_data = '';
+ this.next_out = 0;
+ this.error = ZLIB.inflate(this, flush);
+ if(avail_out >= 0) {
+ return this.output_data;
+ }
+ result += this.output_data;
+ if(this.avail_out > 0) {
+ break;
+ }
+ } while(this.error == ZLIB.Z_OK);
+
+ return result;
+};
+
+ZLIB.z_stream.prototype.inflateReset = function(windowBits)
+{
+ return ZLIB.inflateReset(this, windowBits);
+};
+
+}());
diff --git a/zlib.js b/zlib.js
new file mode 100644
index 0000000..1b6fbba
--- /dev/null
+++ b/zlib.js
@@ -0,0 +1,111 @@
+/* zlib.js -- JavaScript implementation for the zlib.
+ Version: 0.2.0
+ LastModified: Apr 12 2012
+ Copyright (C) 2012 Masanao Izumo
+
+ The original copyright notice (zlib 1.2.6):
+
+ Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
+ (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
+*/
+
+var ZLIB = ( ZLIB || {} ); // ZLIB namespace initialization
+
+// common definitions
+if(typeof ZLIB.common_initialized === 'undefined') {
+ ZLIB.Z_NO_FLUSH = 0;
+ ZLIB.Z_PARTIAL_FLUSH = 1;
+ ZLIB.Z_SYNC_FLUSH = 2;
+ ZLIB.Z_FULL_FLUSH = 3;
+ ZLIB.Z_FINISH = 4;
+ ZLIB.Z_BLOCK = 5;
+ ZLIB.Z_TREES = 6;
+ /* Allowed flush values; see deflate() and inflate() below for details */
+
+ ZLIB.Z_OK = 0;
+ ZLIB.Z_STREAM_END = 1;
+ ZLIB.Z_NEED_DICT = 2;
+ ZLIB.Z_ERRNO = (-1);
+ ZLIB.Z_STREAM_ERROR = (-2);
+ ZLIB.Z_DATA_ERROR = (-3);
+ ZLIB.Z_MEM_ERROR = (-4);
+ ZLIB.Z_BUF_ERROR = (-5);
+ ZLIB.Z_VERSION_ERROR = (-6);
+ /* Return codes for the compression/decompression functions. Negative values
+ * are errors, positive values are used for special but normal events.
+ */
+
+ ZLIB.Z_DEFLATED = 8; /* The deflate compression method (the only one supported in this version) */
+
+ /**
+ * z_stream constructor
+ * @constructor
+ */
+ ZLIB.z_stream = function() {
+ this.next_in = 0; /* next input byte */
+ this.avail_in = 0; /* number of bytes available in input_data */
+ this.total_in = 0; /* total number of input bytes read so far */
+
+ this.next_out = 0; /* next output byte */
+ this.avail_out = 0; /* remaining free space at next_out */
+ this.total_out = 0; /* total number of bytes output so far */
+
+ this.msg = null; /* last error message, null if no error */
+ this.state = null; /* not visible by applications */
+
+ this.data_type = 0; /* best guess about the data type: binary or text */
+ this.adler = 0; /* TODO: adler32 value of the uncompressed data */
+
+ // zlib.js
+ this.input_data = ''; /* input data */
+ this.output_data = ''; /* output data */
+ this.error = 0; /* error code */
+ this.checksum_function = null; /* crc32(for gzip) or adler32(for zlib) */
+ };
+
+ /**
+ * TODO
+ * @constructor
+ */
+ ZLIB.gz_header = function() {
+ this.text = 0; /* true if compressed data believed to be text */
+ this.time = 0; /* modification time */
+ this.xflags = 0; /* extra flags (not used when writing a gzip file) */
+ this.os = 0xff; /* operating system */
+ this.extra = null; /* extra field string or null if none */
+ this.extra_len = 0; /* this.extra.length (only when reading header) */
+ this.extra_max = 0; /* space at extra (only when reading header) */
+ this.name = null; /* file name string or null if none */
+ this.name_max = 0; /* space at name (only when reading header) */
+ this.comment = null; /* comment string or null if none */
+ this.comm_max = 0; /* space at comment (only when reading header) */
+ this.hcrc = 0; /* true if there was or will be a header crc */
+ this.done = 0; /* true when done reading gzip header (not used
+ when writing a gzip file) */
+ };
+
+ ZLIB.common_initialized = true;
+} // common definitions