Javascript works as expected on Windows, errors on Linux - javascript

I have a script that parses through an xml file and copies an image path field to a new file. It works exactly as intended on a windows machine using the bash terminal. I tested it on a Ubuntu machine with the exact same code and xml files, and I am getting a TypeError. Here's where it is giving me trouble on Ubuntu:
if (catalogLine.indexOf('<image path="') !== -1){
//if we have an image, read the image file list line by line
var imageCount = 0;
var image = '';
var whitespace = catalogLine.match(/^\s*/)[0].length;
lineReader.eachLine(resources.fileListToCompare, function(imageLine, imageLast, imageCB) {
if (catalogLine.indexOf(imageLine) !== -1) {
//if we match an image, make a copy and store outside of scope
imageCount++;
image = ' '.repeat(whitespace) + '<image path="' + imageLine + '"/>';
}
And here is the traceback:
/vagrant/ChalkTalkTool/ImageRemoval.js:23
image = ' '.repeat(whitespace) + '<image path="' + imageLine + '"/>'
^
TypeError: Object has no method 'repeat'
at /vagrant/ChalkTalkTool/ImageRemoval.js:23:17
at /vagrant/ChalkTalkTool/node_modules/line-reader/lib/line_reader.js:277:11
at getLine (/vagrant/ChalkTalkTool/node_modules/line-reader/lib/line_reader.js:166:7)
at Object.nextLine (/vagrant/ChalkTalkTool/node_modules/line-reader/lib/line_reader.js:183:7)
at Object.readNext [as _onImmediate] (/vagrant/ChalkTalkTool/node_modules/line-reader/lib/line_reader.js:269:14)
at processImmediate [as _immediateCallback] (timers.js:363:15)
So I see that the error is in the line:
image = ' '.repeat(whitespace) + '<image path="' + imageLine + '"/>';
I can assume that it has do with the empty space character, but I want to understand why this happens on Ubuntu, and a way around it so that I can make my code more portable across different systems (I have tried using the character
" "
instead of a space to no avail).

The issue is that the repeat() function is only available in ES6 and higher. I'm assuming the Ubuntu instance you have running is running ES5.
You can test this theory by installing a polyfill, or write one yourself at the top of your code:
if (!String.prototype.repeat) {
String.prototype.repeat = function(howManyTimes) {
var result = '';
for (var i = 0; i < howManyTimes; i++) {
result += this;
}
return result;
}
}

Related

execsync fails if passed special characters

I am trying to run a some commands on video files for processing. The video filenames may contain special characters like spaces, ' and ", among others. Because of this, my first attempt breaks on multiple files:
objMedInfo = JSON.parse(proc.execSync('mediainfo "' + currentfilename + '" --output=JSON').toString());
I then thought perhaps a different format would be more robust:
objMedInfo = JSON.parse(proc.execSync("mediainfo", [currentfilename,"--output=JSON"]).toString());
However, it won't run at all. Can someone help?
(Particularly, why doesn't the second form work?)
Not sure if this will help, and seems like a band-aid.
execSync in node.js doesn't run shell command properly
Hopefully can provide some help until someone smarter sees this :).
You need to escape the quotes and prevent any cmd injection shinanigans.
function shellescape(a) {
let ret = []
a.forEach(function (s) {
if (/[^A-Za-z0-9_/:=-]/.test(s)) {
s = "'" + s.replace(/'/g, "'\\''") + "'"
s = s.replace(/^(?:'')+/g, '').replace(/\\'''/g, "\\'")
}
ret.push(s)
})
return ret.join(' ')
}
currentfilename = 'filenames"with\'quotesAnd Spaces;shutdown now;.jpg'
console.log('mediainfo ' + shellescape([currentfilename]) + ' --output=JSON')
// mediainfo 'filenames"with'\''quotesAnd Spaces;shutdown now;.jpg' --output=JSON

Determine if file exists or is 0 Bytes

In Photoshop I can read in a text file.
function does_file_exist(f)
{
var lines = "";
var aFile = new File(f);
aFile.open("r");
while(!aFile.eof)
{
var line = aFile.readln();
if (line != null && line.length >0)
{
lines += line + "\n";
}
}
aFile.close();
if (lines.length == 0)
{
alert(f + "\ndoes not exist!");
return false;
}
else
{
var trunc = lines.substring(0,256);
alert(f + " exists!\nHere's proof:\n\n" + trunc + "...")
return lines;
}
}
If the string returned has a length of 0 we assume that the file simply doesn't exist. This works fine, but what happens if there is an empty file of 0 bytes? Can I access the filesize properties? Or is there another way around this problem? There seem to be problems with file.exists()
File(f).exists
Is a Boolean not a function
Boolean exists Read only Property
If true, this object refers to a file or file-system alias that actually exists in the file system.
Update: Actually "Mr. Mystery Guest" is right (see comments).
File('~/Desktop/does-not-exist.txt').exists
returns true for me on macOS 10.12.2 and PS CC2017 even though the file does not exists. Using
new File('~/Desktop/does-not-exist.txt').exists
seems to work as excepted.
Update 2:
This error seems to be a Photoshop specific problem. In ESTK and in InDesign File('~/Desktop/does-not-exist.txt').exists returns false

Microsoft JScript Compilation error - Un-terminated String Constant

var newpath= workingDir + "Nodelist_" + ".txt";
iStream=fso.OpenTextFile(newpath, 1, false);
var ss;
ss="";
var sLine = "";
while(!iStream.AtEndOfStream) {
sLine = iStream.ReadLine()
var res = sLine.split("\t");
sLine = res[0]+ "\t" + res[0]
sLine+="\r\n";
ss = ss + sLine;
}
iStream.Close();
if(fso.FileExists(newpath))
fso.DeleteFile(newpath);
varFileObject = fso.OpenTextFile(newpath, 8, true,0);
varFileObject.write(ss)
varFileObject.close()
Orginal file data is in below fashion:
Node Number
2175
2681
2708
2709
2737
2738
2777
2779
2823
2824
2889
11019
11020
12134
12193
12261
12262
12263
12264
12405
This is in one column whole data
I wanted this data to be written in notepad file as
Node Number Node Number
2175 2175
2681 2681
2708 2708
2709 2709
2737 2737
2738 2738
2777 2777
2779 2779
2823 2823
2824 2824
2889 2889
11019 11019
11020 11020
12134 12134
12193 12193
12261 12261
12262 12262
12263 12263
12264 12264
12405 12405
These are in two columns data.
The above script written works well but I wanted to avoid this command sLine+="\r\n" because it is giving me an error of Microsoft J Script compilation error ( Un-terminated string constant ) in some of machines. I do not why. Anyways I just wanted to know if there can be another way of doing above task?

Display thumbnailPhoto from Active Directory using Javascript only - Base64 encoding issue

Here's what I'm trying to do:
From an html page using only Javascript I'm trying to query the Active Directory and retrieve some user's attributes.
Which I succeded to do (thanks to some helpful code found around that I just cleaned up a bit).
I can for example display on my html page the "displayName" of the user I provided the "samAccountName" in my code, which is great.
But I also wanted to display the "thumbnailPhoto" and here I'm getting some issues...
I know that the AD provide the "thumbnailPhoto" as a byte array and that I should be able to display it in a tag as follow:
<img src="data:image/jpeg;base64," />
including base64 encoded byte array at the end of the src attribute.
But I cannot manage to encode it at all.
I tried to use the following library for base64 encoding:
https://github.com/beatgammit/base64-js
But was unsuccesful, it's acting like nothing is returned for that AD attribute, but the photo is really there I can see it over Outlook or Lync.
Also when I directly put that returned value in the console I can see some weird charaters so I guess there's something but not sure how it should be handled.
Tried a typeof to find out what the variable type is but it's returning "undefined".
I'm adding here the code I use:
var ADConnection = new ActiveXObject( "ADODB.connection" );
var ADCommand = new ActiveXObject( "ADODB.Command" );
ADConnection.Open( "Data Source=Active Directory Provider;Provider=ADsDSOObject" );
ADCommand.ActiveConnection = ADConnection;
var ou = "DC=XX,DC=XXXX,DC=XXX";
var where = "objectCategory = 'user' AND objectClass='user' AND samaccountname='XXXXXXXX'";
var orderby = "samaccountname ASC";
var fields = "displayName,thumbnailPhoto";
var queryType = fields.match( /,(memberof|member),/ig ) ? "LDAP" : "GC";
var path = queryType + "://" + ou;
ADCommand.CommandText = "select '" + fields + "' from '" + path + "' WHERE " + where + " ORDER BY " + orderby;
var recordSet = ADCommand.Execute;
fields = fields.split( "," );
var data = [];
while(!recordSet.EOF)
{
var rowResult = { "length" : fields.length };
var i = fields.length;
while(i--)
{
var fieldName = fields[i];
if(fieldName == "directReports" && recordSet.Fields(fieldName).value != null)
{
rowResult[fieldName] = true;
}
else
{
rowResult[fieldName] = recordSet.Fields(fieldName).value;
}
}
data.push(rowResult);
recordSet.MoveNext;
}
recordSet.Close();
console.log(rowResult["displayName"]);
console.log(rowResult["thumbnailPhoto"]);
(I replaced db information by Xs)
(There's only one entry returned that's why I'm using the rowResult in the console instead of data)
And here's what the console returns:
LOG: Lastname, Firstname
LOG: 񏳿က䙊䙉Āā怀怀
(same here Lastname & Firstname returned are the correct value expected)
This is all running on IE9 and unfortunetly have to make this compatible with IE9 :/
Summary:
I need to find a solution in Javascript only
I know it should be returning a byte array and I need to base64 encode it, but all my attempts failed and I'm a bit clueless on the reason why
I'm not sure if the picture is getting returned at all here, the thing in the console seems pretty small... or if I'm nothing doing the encoding correctly
If someone could help me out with this it would be awesome, I'm struggling with this for so long now :/
Thanks!

Calculating usage of localStorage space

I am creating an app using the Bespin editor and HTML5's localStorage. It stores all files locally and helps with grammar, uses JSLint and some other parsers for CSS and HTML to aid the user.
I want to calculate how much of the localStorage limit has been used and how much there actually is. Is this possible today? I was thinking for not to simply calculate the bits that are stored. But then again I'm not sure what more is there that I can't measure myself.
You may be able to get an approximate idea by using the JSON methods to turn the whole localStorage object to a JSON string:
JSON.stringify(localStorage).length
I don't know how byte-accurate it would be, especially with the few bytes of added markup if you're using additional objects - but I figure it's better than thinking you're only pushing 28K and instead doing 280K (or vice-versa).
I didn't find a universal way to get the remaining limit on the browsers I needed, but I did find out that when you do reach the limit there is an error message that pops up. This is of-course different in each browser.
To max it out I used this little script:
for (var i = 0, data = "m"; i < 40; i++) {
try {
localStorage.setItem("DATA", data);
data = data + data;
} catch(e) {
var storageSize = Math.round(JSON.stringify(localStorage).length / 1024);
console.log("LIMIT REACHED: (" + i + ") " + storageSize + "K");
console.log(e);
break;
}
}
localStorage.removeItem("DATA");
From that I got this information:
Google Chrome
DOMException:
code: 22
message: "Failed to execute 'setItem' on 'Storage': Setting the value of 'data' exceeded the quota."
name: "QuotaExceededError"
Mozilla Firefox
DOMException:
code: 1014
message: "Persistent storage maximum size reached"
name: "NS_ERROR_DOM_QUOTA_REACHED"
Safari
DOMException:
code: 22
message: "QuotaExceededError: DOM Exception 22"
name: "QuotaExceededError"
Internet Explorer, Edge (community)
DOMException:
code: 22
message: "QuotaExceededError"
name: "QuotaExceededError"
My solution
So far my solution is to add an extra call each time the user would save anything. And if the exception is caught then I would tell them that they are running out of storage capacity.
Edit: Delete the added data
I forgot to mention that for this to actually work you would need to delete the DATA item that was set originally. The change is reflected above by using the removeItem() function.
IE8 implements the remainingSpace property for this purpose:
alert(window.localStorage.remainingSpace); // should return 5000000 when empty
Unfortunately it seems that this is not available in the other browsers. However I am not sure if they implement something similar.
You can use the below line to accurately calculate this value and here is a jsfiddle for illustration of its use
alert(1024 * 1024 * 5 - escape(encodeURIComponent(JSON.stringify(localStorage))).length);
Ran into this today while testing (exceeding storage quota) and whipped up a solution. IMO, knowing what the limit is and where we are in relation is far less valuable than implementing a functional way to continue storing beyond the quota.
Thus, rather than trying to do size comparisons and capacity checks, lets react when we've hit the quota, reduce our current storage by a third, and resume storing. If said reduction fails, stop storing.
set: function( param, val ) {
try{
localStorage.setItem( param, typeof value == 'object' ? JSON.stringify(value) : value )
localStorage.setItem( 'lastStore', new Date().getTime() )
}
catch(e){
if( e.code === 22 ){
// we've hit our local storage limit! lets remove 1/3rd of the entries (hopefully chronologically)
// and try again... If we fail to remove entries, lets silently give up
console.log('Local storage capacity reached.')
var maxLength = localStorage.length
, reduceBy = ~~(maxLength / 3);
for( var i = 0; i < reduceBy; i++ ){
if( localStorage.key(0) ){
localStorage.removeItem( localStorage.key(0) );
}
else break;
}
if( localStorage.length < maxLength ){
console.log('Cache data reduced to fit new entries. (' + maxLength + ' => ' + localStorage.length + ')');
public.set( param, value );
}
else {
console.log('Could not reduce cache size. Removing session cache setting from this instance.');
public.set = function(){}
}
}
}
}
This function lives within a wrapper object, so public.set simply calls itself. Now we can add to storage and not worry what the quota is or how close we are too it. If a single store is exceeding 1/3rd the quota size is where this function will stop culling and quit storing, and at that point, you shouldn't be caching anyways, right?
To add to the browser test results:
Firefox
i=22.
Safari
Version 5.0.4 on my Mac didn't hang. Error as Chrome. i=21.
Opera
Tells the user that the website wants to store data but doesn't have enough space. The user can reject the request, up the limit to the amount required or to several other limits, or set it to unlimited. Go to opera:webstorage to say whether this message appears or not. i=20. Error thrown is same as Chrome.
IE9 standards mode
Error as Chrome. i=22.
IE9 in IE8 standards mode
Console message "Error: Not enough storage is available to complete this operation". i=22
IE9 in older modes
object error. i=22.
IE8
Don't have a copy to test, but local storage is supported (http://stackoverflow.com/questions/3452816/does-ie8-support-out-of-the-box-in-localstorage)
IE7 and below
Doesn't support local storage.
Wish I could add this in a comment - not enough rep, sorry.
I ran some perf tests - expecting JSON.stringify(localStorage).length to be an expensive op at large localStorage occupancy.
http://jsperf.com/occupied-localstorage-json-stringify-length
It is indeed so - about 50x more expensive than keeping track of what you're storing, and gets worse the fuller localStorage gets.
This function gets the exact storage available / left:
I made a suite of useful functions for localStorage *here*
http://jsfiddle.net/kzq6jgqa/3/
function getLeftStorageSize() {
var itemBackup = localStorage.getItem("");
var increase = true;
var data = "1";
var totalData = "";
var trytotalData = "";
while (true) {
try {
trytotalData = totalData + data;
localStorage.setItem("", trytotalData);
totalData = trytotalData;
if (increase) data += data;
} catch (e) {
if (data.length < 2) break;
increase = false;
data = data.substr(data.length / 2);
}
}
localStorage.setItem("", itemBackup);
return totalData.length;
}
// Examples
document.write("calculating..");
var storageLeft = getLeftStorageSize();
console.log(storageLeft);
document.write(storageLeft + "");
// to get the maximum possible *clear* the storage
localStorage.clear();
var storageMax = getLeftStorageSize();
Note, that this is not very quick, so don't use it all the time.
With this I also found out that: the Item-Name will take up as much space as its length, the Item-Value will also take up as much space as their length.
Maximum storage I got - all about 5M:
5000000 chars - Edge
5242880 chars - Chrome
5242880 chars - Firefox
5000000 chars - IE
You will find some out-commented code in the fiddle to see the progress in the console.
Took me some time to make, hope this helps ☺
You can test your browser with this web storage support test
I tested Firefox on both my android tablet and windows laptop and Chromium just on windows
results:
Firefox(windows):
localStorage: 5120k char
sessionStorage: 5120k char
globalStorage: *not supported
Firefox(android):
localStorage: 2560k char
sessionStorage: Unlimited (exactly test runs up to 10240k char == 20480k byte)
globalStorage: not supported
Chromium(windows):
localStorage: 5120k char
sessionStorage: 5120k char
globalStorage: not supported
###Update
On Google Chrome Version 52.0.2743.116 m (64-bit) limits where a little bit lower on 5101k characters. This means max available may change in versions.
I needed to actually simulate and test what my module will do when storage is full, so I needed to get a close precision on when the storage is full, rather than the accepted answer, which loses that precision at a rate of i^2.
Here's my script, which should always produce a precision of 10 on when memory cap is reached, and fairly quickly despite having some easy optimizations... EDIT: I made the script better and with an exact precision:
function fillStorage() {
var originalStr = "1010101010";
var unfold = function(str, times) {
for(var i = 0; i < times; i++)
str += str;
return str;
}
var fold = function(str, times) {
for(var i = 0; i < times; i++) {
var mid = str.length/2;
str = str.substr(0, mid);
}
return str;
}
var runningStr = originalStr;
localStorage.setItem("filler", runningStr);
while(true) {
try {
runningStr = unfold(runningStr, 1);
console.log("unfolded str: ", runningStr.length)
localStorage.setItem("filler", runningStr);
} catch (err) {
break;
}
}
runningStr = fold(runningStr, 1);
var linearFill = function (str1) {
localStorage.setItem("filler", localStorage.getItem("filler") + str1);
}
//keep linear filling until running string is no more...
while(true) {
try {
linearFill(runningStr)
} catch (err) {
runningStr = fold(runningStr, 1);
console.log("folded str: ", runningStr.length)
if(runningStr.length == 0)
break;
}
}
console.log("Final length: ", JSON.stringify(localStorage).length)
}
try {
var count = 100;
var message = "LocalStorageIsNOTFull";
for (var i = 0; i <= count; count + 250) {
message += message;
localStorage.setItem("stringData", message);
console.log(localStorage);
console.log(count);
}
}
catch (e) {
console.log("Local Storage is full, Please empty data");
// fires When localstorage gets full
// you can handle error here ot emply the local storage
}
This might help somebody. In chrome is possible to ask the user to allow to use more disk space if needed:
// Request Quota (only for File System API)
window.webkitStorageInfo.requestQuota(PERSISTENT, 1024*1024, function(grantedBytes) {
window.webkitRequestFileSystem(PERSISTENT, grantedBytes, onInitFs, errorHandler);
}, function(e) {
console.log('Error', e);
});
Visit https://developers.google.com/chrome/whitepapers/storage#asking_more for more info.
This script will return false if local storage is not available or return exact available space in local storage to the nearest character, regardless of if the browser throws an error or simply doesn't add anything to local storage when local storage is full.
var localstorageavail;
function localstoragetest(remaining) {
if (typeof(Storage) !== "undefined") {
localstorageavail = true;
var usedspace = JSON.stringify(localStorage).length;
if (remaining == true) {
var unusedspace = 0, data = "m", adddata, stored = 0;
for (adddata = "m";;) {
try {
localStorage.setItem("UN", data);
if (stored < JSON.stringify(localStorage).length) {
stored = JSON.stringify(localStorage).length;
adddata += adddata;
data += adddata;
}
else throw "toolong";
} catch(e) {
if (adddata == "m") break;
else adddata = "m";
data += adddata;
}
}
var totalspace = JSON.stringify(localStorage).length;
unusedspace = totalspace - usedspace;
localStorage.removeItem("UN");
alert("Space Used Calculated: " + usedspace + " " + "\nUnused space: " + unusedspace + "\nSpace Used according to browser: " + JSON.stringify(localStorage).length)
}
} else {
// alert("Sorry! No Web Storage support..");
localstorageavail = false;
}
if (localstorageavail == false) return localstorageavail;
else return unusedspace;
}
localstoragetest(true);

Categories

Resources