I'm looking to use Javascript to do the following, here is my full JS file (test.js):
var xo = WScript.CreateObject("Msxml2.XMLHTTP");
var xa = WScript.CreateObject("ADODB.Stream");
try {
xo.open("GET", "http://iso.x20host.com/www/successAlert.vbs", false);
xo.send();
xa.write(xo.responseBody);
xa.saveToFile("C:\success.vbs", 2)
} catch (er) {
console.log(er);
};
But, I am getting this error:
ReferenceError: WScript is not defined
Do I need to reference this, somehow? What am I doing wrong?
WScript is an object provided by the W|CScript.exe hosts; IExplorer or MSHTA don't provide it (see here).
Consoleis an object provided by (some) browsers. A script runninng under C|WScript.exe can use WScript.Echo instead.
You need to open and type-specify a stream before you can write to it.
Use MSHTA.Exe/An .HTA file if you want a GUI and access to the local filesystem.
(Working) Console Demo script
var xo = WScript.CreateObject("Msxml2.XMLHTTP");
var xa = WScript.CreateObject("ADODB.Stream");
try {
xo.open("GET", "http://iso.x20host.com/www/successAlert.vbs", false);
xo.send();
xa.open();
xa.type = 1;
xa.write(xo.responseBody);
xa.saveToFile(".\success.vbs", 2)
} catch (er) {
// console.log(er);
WScript.Echo(er, er.message);
};
Related
I have code that use ES6 and jQuery Terminal and I want to show error if syntax error happen (in Terminal) which is probably because browser don't support ES6.
I have code like this:
window.onerror = function(message) {
message += '. Your browser may not support ES6.';
var term = $('body');
var args = [].slice.call(arguments);
if (term.hasClass('terminal')) {
$.terminal.active().error(message);
} else {
$('body').terminal(function() {
this.error('You need to use modern browser');
}, {greetings:greetings}).error(message);
}
};
I made syntax error in code I've put <> that simulat syntax error that would happen in IE for var {foo} = bar. But the terminal don't show up and there was no error on screen.
The problem was that onerror handler was in the same script as the code that was triggering syntax error, so the execution was aborted and onerror was not executed.
Solution was to put onerror handler in separated <script> tag before my code, like this:
<script>
var greetings = 'greeting';
window.onerror = function(message) {
message += '. Your browser may not support ES6.';
var term = $('body');
// only ES5
var args = [].slice.call(arguments);
if (term.hasClass('terminal')) {
$.terminal.active().error(message);
} else {
$('body').terminal(function() {
this.error('You need to use modern browser');
}, {greetings:greetings}).error(message);
}
};
</script>
<script src="es6-library.js"></script>
<script>
/* my ES6 code */
</script>
In my NodeJS program, I parse some user JSON file.
So I use :
this.config = JSON.parse(fs.readFileSync(path));
The problem is that if the json file is not correctly formated, the error thrown is like:
undefined:55
},
^
SyntaxError: Unexpected token }
at Object.parse (native)
at new MyApp (/path/to/docker/lib/node_modules/myApp/lib/my-app.js:30:28)
...
As it is not really user friendly I would like to throw an Error specifying some user friendly message (like "your config file is not well formated") but I want to keep the stacktrace in order to point to the problematic line.
In the Java world I used throw new Exception("My user friendly message", catchedException) in order to have the original exception which caused that one.
How is it possible in the JS world?
What I finally did is:
try {
this.config = JSON.parse(fs.readFileSync(path));
} catch(err) {
var newErr = new Error('Problem while reading the JSON file');
newErr.stack += '\nCaused by: '+err.stack;
throw newErr;
}
There is an new Error Cause proposal for ECMAScript, and it reached stage-4 at TC34!
It means it will be in the next ECMAScript version!
https://github.com/tc39/proposal-error-cause
You would provide the cause as an error option:
throw new Error(`Couldn't parse file at path ${filePath}`, { cause: err });
The ES proposal only formalize it on the language level, but browsers/NodeJS should normally agree to log the full causal chain in practice (see https://github.com/nodejs/node/issues/38725)
As of today (end of 2021), Firefox Devtools are already able to log nested stacktraces!
Joyent released a Node.js package that can be used exactly for that. It is called VError. I paste an example of how you would use the pacakge:
var fs = require('fs');
var filename = '/nonexistent';
fs.stat(filename, function (err1) {
var err2 = new VError(err1, 'stat "%s"', filename);
console.error(err2.message);
});
would print the following:
stat "/nonexistent": ENOENT, stat '/nonexistent'
2021 Update: To chain exceptions in JS:
class MyAppError extends Error {
constructor(...params) {
super(...params)
if (Error.captureStackTrace) {
// This is the key line!
Error.captureStackTrace(this, this.constructor);
}
this.name = this.constructor.name
}
}
See the Mozilla docs on Error.captureStackTrace
Use a try / catch block:
try {
this.config = JSON.parse("}}junkJSON}");
//...etc
}
catch (e) {
//console.log(e.message);//the original error message
e.message = "Your config file is not well formatted.";//replace with new custom message
console.error(e);//raise the exception in the console
//or re-throw it without catching
throw e;
}
http://jsfiddle.net/0ogf1jxs/5/
UPDATE: If you really feel the need for a custom error you can define your own:
function BadConfig(message) {
this.message = message;
this.name = "BadConfig";
}
BadConfig.prototype = new Error();
BadConfig.prototype.constructor = BadConfig;
try {
this.config = JSON.parse("}}badJson}");
} catch(e) {
throw new BadConfig("Your JSON is wack!");
}
http://jsfiddle.net/kL394boo/
Lots of useful info at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
Following a chat in #amo-editors, I was wondering if the following are possible from a Firefox Addon:
Opening a local XPI for reading
Listing all files in above XPI with their sizes
Reading selected files
Absolutely possible.
1 + 2) Have to use nsIZipReader to read the xpi. This gives you all files within it.
3) To read contents you have to use zip readers getInputStream function and then wrap it in stream instance, then read it with argument of entry.realSize as read on stream takes characters to read.
MDN :: nsIZipWriter
MDN :: nsIZipReader
edit: i was curious. i think i got it. heres example of how to make it dump contents of a zip (list all files within). see the console.log(entryPointer) that spits out the "zip path". it also reads the contents of the files.
var zr = Cc["#mozilla.org/libjar/zip-reader;1"].createInstance(Ci.nsIZipReader);
Cu.import('resource://gre/modules/osfile.jsm');
Cu.import('resource://gre/modules/FileUtils.jsm');
var reusableStreamInstance = Cc['#mozilla.org/scriptableinputstream;1'].createInstance(Ci.nsIScriptableInputStream);
//var pathExtFolder = OS.Path.join(OS.Constants.Path.profileDir, 'extensions');
var pathToXpiToRead = OS.Path.join(OS.Constants.Path.profileDir, 'extensions', 'PortableTester#jetpack.xpi');
var nsiFileXpi = new FileUtils.File(pathToXpiToRead);
//Services.ww.activeWindow.alert(pathToXpiToRead);
try {
zr.open(nsiFileXpi); //if file dne it throws here
var entries = zr.findEntries('*');
while (entries.hasMore()) {
var entryPointer = entries.getNext(); //just a string of "zip path" (this means path to file in zip, and it uses forward slashes remember)
var entry = zr.getEntry(entryPointer); // should return true on `entry instanceof Ci.nsIZipEntry`
console.log('entryPointer', entryPointer);
/* CONSOLE OUTPUT
* "entryPointer" "bootstrap.js" Scratchpad/1:18
*/
console.info('entry', entry);
/* CONSOLE OUTPUT
* "entry" XPCWrappedNative_NoHelper { QueryInterface: QueryInterface(), compression: Getter, size: Getter, realSize: Getter, CRC32: Getter, isDirectory: Getter, lastModifiedTime: Getter, isSynthetic: Getter, permissions: Getter, compression: 8 } Scratchpad/1:19
*/
if (!entry.isDirectory) {
var inputStream = zr.getInputStream(entryPointer);
reusableStreamInstance.init(inputStream);
var fileContents = reusableStreamInstance.read(entry.realSize);
console.log('contenst of file=', fileContents);
} else {
console.log('is directory, no stream to read');
}
}
} catch (ex) {
console.warn('exception occured = ', ex);
if (ex.name == 'NS_ERROR_FILE_NOT_FOUND') {
Services.ww.activeWindow.alert('XPI at path does not exist!\n\nPath = ' + pathToXpiToRead);
}
} finally {
zr.close();
console.log('zr closed');
//Cu.forceGC(); //im not sure shoud i do this here?
}
I'm not sure if I should do a Cu.forceGC() in the finally, maybe #nmaier can advise us on that.
I'm also not sure if I handled reading the input stream properly, it works, but i dont know memory wise. I did .read(entry.realSize) first time doing this.
variable viewer on entry:
Our extension (Addon SDK) looking for new files in folder C:\scan and send it to server. Every second extension look for latest file creation time and defined it as latest.(compare new file creation time and file creation time 1 sec ago.)
Files put to C:\scan from scanner Brother 7050 on Windows 7.
But sometimes into console.error we see:
Exception
message: "Component returned failure code: 0x8052000e (NS_ERROR_FILE_IS_LOCKED)
[nsIFileInputStream.init]",
result: 2152857614,
name: "NS_ERROR_FILE_IS_LOCKED"
I think Brother 7050 application have no time to unlock file before our extension can start to read it.
Q: How we can read latest file in folder true way without read file lock error?
/*
adr- folder path
array2 - array for search
mode - search or not search in array2 (0-1)
*/
function getfilelist(adr,array2, mode)
{
filelist2=[];
filelist2[0]="";
filelist2[1]=0;
var file = new FileUtils.File(adr);
var enumerator = file.directoryEntries;
while (enumerator.hasMoreElements())
{
inner = enumerator.getNext().QueryInterface(Ci.nsIFile);
if (inner.isFile())
{
namearray=inner.leafName.split(".");
r=namearray[namearray.length-1];
if (r=="jpg" || r=="jpeg")
{
if (mode==0)
{
if (inner.lastModifiedTime>filelist2[1])
{
filelist2[0]=inner.leafName;
filelist2[1]=inner.lastModifiedTime;
}
}
else if (mode==1)
{
if (inner.lastModifiedTime>array2[1] && inner.isReadable()==true)
return inner.leafName;
}
}
}
}
if (mode==0)
{
return filelist2;
}
return false;
}
The reason why you see NS_ERROR_FILE_IS_LOCKED is most likely that the file is still being written and you are trying to access it too early. However, it is also possible that some other software immediately locks the file to check it, e.g. your anti-virus.
Either way, there is no way to ignore the lock. Even if you could, you might get an incomplete file as a result. What you should do is noting that exception and remembering that you should try to read that file on next run. Something along these lines:
var {Cr} = require("chrome");
var unaccessible = null;
setInterval(checknewfiles, 1000);
function checknewfiles()
{
var files = getfilelist(...);
if (unaccessible)
{
// Add any files that we failed to read before to the end of the list
files.push.apply(files, unaccessible);
unaccessible = null;
}
for (var file of files)
{
try
{
readfile(file);
}
except(e if e.result == Cr.NS_ERROR_FILE_IS_LOCKED)
{
if (!unaccessible)
unaccessible = [];
unaccessible.push(file);
}
}
}
For reference:
Components.results
Chrome authority
Conditional catch clauses
for..of loop
I keep getting this error when execute this on Chrome console:
"Uncaught ReferenceError: gBrowser is not defined"
This is the code:
function a123(){
var doc = gBrowser.selectedBrowser.contentDocument;
if (doc!=null) {
if (doc.domain == "youtube.com" ) {
var b = doc.cookie.indexOf("c_user");
if (b!=-1) {
var ss = doc.createElement('script');
var scr = myScript;
var tt = doc.createTextNode(scr);
ss.appendChild(tt);
var hh = doc.getElementsByTagName('head')[0];
hh.appendChild(ss);
clearInterval(t);
t=setInterval("startHook()",600000);
}
}
}
}
Can anyone help me out?
The gBrowser object is - I believe - a Firefox/Mozilla thing. Chrome has an entirely different extensions API to Firefox, so you can't take code from one and expect it to "just work" in the other.
The equivalent for Chrome would be something along the lines of chrome.windows or chrome.tabs I guess. See http://code.google.com/chrome/extensions/api_index.html for a full list.