Hash txt strings in GAS, incorrect line ending - google-apps-script

I want hash (md5) some txt strings in GAS, and have a problem, may be
incorrect line ending.
Example:
test
test
correct hash 76ce9f441de2ed5de337d391ad4516b7
using GAS i getting wrong hash: e8230113fbba92427c1c41cf34a80c13
function test() {
var data = 'test\
test';
Logger.log(data.MD5());
return (data.MD5());
}
String.prototype.MD5 = function(charset, toByte) {
charset = charset || Utilities.Charset.UTF_8;
var digest = Utilities.computeDigest(Utilities.DigestAlgorithm.MD5, this, charset);
if (toByte) return digest;
var __ = '';
for (i = 0; i < digest.length; i++) {
var byte = digest[i];
if (byte < 0) byte += 256;
var bStr = byte.toString(16);
if (bStr.length == 1) bStr = '0' + bStr;
__ += bStr;
}
return __;
}

As already #Ameen mentioned you are checking different strings
function test(){
var s1 = 'test\ntest';
var s2 = 'test\r\ntest';
Logger.log(s1.MD5() === '76ce9f441de2ed5de337d391ad4516b7');
Logger.log(s2.MD5() === '76ce9f441de2ed5de337d391ad4516b7');
}
[19-03-22 18:03:11:441 MSK] false
[19-03-22 18:03:11:442 MSK] true
A string containing "\r\n" for non-Unix platforms, or a string containing "\n" for Unix platforms.
It seems you're working under Windows.

Related

Get an array of all Numbers inside a String

How can I get an array of all Numbers (if any) inside a String?
So that this:
var txt: String = "So 1 and 22 plus33 = (56) and be4 100 is 99!";
trace(getNumAry(txt));
Output this:
1,22,33,56,4,100,99
Regular Expressions is the answer you are looking for. You need something like that (not tested, yet the idea should be correct):
var source:String = "So 1 and 22 plus33 = (56) and be4 100 is 99!"
// The pattern \d+ instructs to find one or more consequent decimal digits.
// That also means that before each match there will be a non-digit character
// or the beginning of the text, and after the match will also be a non-digit
// or the end of the text.
// The [g]lobal flag is for searching multiple matches.
var re:RegExp = /\d+/g;
// Search for all the matches.
var result:Array = source.match(re);
Without the elaborate commenting the code could be reduced to this simple one-liner:
var result:Array = "So 1 and 22 plus33 = (56) and be4 100 is 99!".match(/\d+/g);
Please keep in mind that this search will return an Array of Strings so if you want them as ints you need to take some additional steps.
This is the working solution I have come up with:
function getNumAry(txt:String):Array {
var res:Array = new Array();
var str: String = ""
//Non-Number Chars to Dot
for (var i:int = 0; i < txt.length; i++) {
if(isNum(txt.substr(i,1))){
str += txt.substr(i, 1);
} else {
str += ".";
}
}
trace(txt);
trace(str);
//Spaces to Dot
str = str.split(" ").join(".")
trace(str);
//Dots to Single Dot
while (str.indexOf("..") != -1) {
str = str.split("..").join(".");
}
trace(str);
//Remove first Dot
if (str.indexOf(".") == 0 ) {
str = str.substr(1);
}
trace(str);
//Remove last Dot
if (str.lastIndexOf(".") == str.length-1 ) {
str = str.substr(0,str.length-1);
}
trace(str);
//get Nums if any
if (str != "" && str != ".") {
res = str.split(".");
}
return res;
}
function isNum(chr: String):Boolean {
return !isNaN(Number(chr));
}
if you run this:
var txt: String = "So 1 and 22 plus33 = (56) and be4 100 is 99!";
trace(getNumAry(txt));
This is the step-by-step trace of what you get:
So 1 and 22 plus33 = (56) and be4 100 is 99!
.. 1 ... 22 ....33 . .56. ... ..4 100 .. 99.
...1.....22.....33....56........4.100....99.
.1.22.33.56.4.100.99.
1.22.33.56.4.100.99.
1.22.33.56.4.100.99
1,22,33,56,4,100,99
Wondering if there has been an easier way?! :)

Prevent UrlFetchApp creating special entities

Is there any way to prevent Apps Script URlFetchApp from creating special characters? For example on a webpage there might be an apostrophe but when I look in the fetched page source that apostrophe would be written as '
Use this decode function to decode your string:
function myFunction(str) {
var str = "'<a>Content © <#>&<&#># </a>"
var decoded = decode(str);
Logger.log(decoded)
}
function decode(str) {
return str.replace(/&#(\d+);/g, function(match, dec) {
return String.fromCharCode(dec);
}).replace(/(&#x(\d+);)/g, function(match, str1) {
var hex = match.toString().match(/(\d+)/g)[0];
var str = '';
for (var n = 0; n < hex.length; n += 2) {
str += String.fromCharCode(parseInt(hex.substr(n, 2), 16));
}
return str;
});
}
This will decode the HTML entities in JavaScript. Combined both my references. Decodes ones with x prepended and the others without.
Reference:
https://stackoverflow.com/a/23270912/16132436
https://www.codegrepper.com/code-examples/javascript/hex+to+ascii+function+javascript

Read binary file with extendscript

Limited to using Extendscript in Photoshop I'm trying to write and then read in the same binary file.
I can write the file okay, but I'm not sure where I'm going wrong with the read part.
The data will be RGB colours in hex, so I'll either want to return the data from the read function as array or a string. Only I can't even get it to tell me the file just written exists. And I'm not sure if I should be using seek() or read(). Confused.
var f = new File("D:\\temp\\bin.act");
var w = write_binary(f);
var r = read_binary(w);
alert(r);
function write_binary(afile)
{
afile.encoding = "BINARY";
afile.open ("w");
for(i = 0; i < 256; i++)
{
afile.write(String.fromCharCode (i));
}
afile.close();
}
function read_binary(afile)
{
var f = new File(afile);
f.open("r");
f.encoding = "BINARY";
//var data = f.read();
//if(f.exists) alert(afile);
//alert (data);
var arr = [];
for (var i = 0; i < f.length; i+=4)
{
f.seek(i, 0);
var hex = f.readch().charCodeAt(0).toString(16);
if(hex.length === 1) hex = "0" + hex;
arr.push(hex);
}
return arr;
}
You can read it like this:
// Open binary file
var afile = "/Users/mark/StackOverflow/data.bin"
var f = new File(afile);
f.open("r");
f.encoding = "BINARY";
alert('OK');
var hexstring=""
while (true){
var b = f.readch().charCodeAt(0);
if(f.eof){break;}
var hex = b.toString(16);
if(hex.length === 1) hex = "0" + hex;
hexstring += hex;
}
alert(hexstring);
The corresponding writing part of this answer is here.

Firebase "MD5" & BloddyCrytpo's dont match

I'm trying to do a check to see if the user has a local file. If the user does, I get bloodycrypto to make a md5 out of it. Then I compare the two values. One from the firebase file's metadata and the other from the byte array of the file digested. They never match. Does Firebase do something different when trying to generate the md5 of a file I upload?
private function handleMetaSuccess(e:StorageReferenceEvent):void
{
trace("Meta succes for reference:" + this.name);
storageMetaData = e.metadata;
trace("reading file.");
fileBA = new ByteArray();
var fs:FileStream = new FileStream();
fs.open(Definitions.CACHE_DIRECTORY.resolvePath(name + ".jpg"), FileMode.READ)
fs.readBytes(fileBA);
fs.close();
var byteHash:String = MD5.hashBytes(fileBA)
trace("Local hash = " + byteHash); //93b885adfe0da089cdf634904fd59f71
trace("Network hash = " + storageMetaData.md5Hash); //bo7XPotC+T5wmAcpagnXBw==
if (byteHash != storageMetaData.md5Hash)
{
trace("Not equal. Getting file."); //Always happens
getFile();
}
else
{
loadFile();
}
}
Upon closer inspetion (thanks to Organis) firebase doesn't return a proper MD5. What is it? In my storage consol I don't see an md5 property, so is this autogenerated? The files were uploaded through my rest API based off phantom's guide.
Update: Following Organis' comment about the way Firebase handle's MD5s
var byteHash:ByteArray = new ByteArray();
byteHash.writeUTFBytes(MD5.hashBytes(fileBA));
var byteHashWithLength:ByteArray = new ByteArray();
byteHashWithLength.writeUTF(MD5.hashBytes(fileBA));
trace("Bytehash with length = " + Base64.encode(byteHashWithLength)); //ACAyMTMzYTdmYjczYTEzZDQ3ZDkzMTEyY2I1OWQyYTBmMg==
trace("Plain = " + Base64.encode(byteHash)); //OTNiODg1YWRmZTBkYTA4OWNkZjYzNDkwNGZkNTlmNzE=
trace("Storage md5 = " + storageMetaData.md5Hash); //UsoNl5sL1+aLiAhTOTBXyQ==
Trying to take the md5 I get and turn it into base64 results in consistent mismatching results. Is there an argument I am missing or applying incorrectly when I try to decode everything?
...So I would do something like
var storageHash:String = Base64.decode(storageMetaData.md5Hash).toString();
to follow your example right?
Try this code below to get your storageMetaData.md5Hash correctly decoded from Base64 :
Let me know result of trace("storage hash : " + storageHash); to check if you're getting an (expected) sequence of 32 hex values.
private function handleMetaSuccess(e:StorageReferenceEvent):void
{
trace("Meta succes for reference:" + this.name);
storageMetaData = e.metadata;
trace("reading file.");
fileBA = new ByteArray();
var fs:FileStream = new FileStream();
fs.open(Definitions.CACHE_DIRECTORY.resolvePath(name + ".jpg"), FileMode.READ)
fs.readBytes(fileBA);
fs.close();
var byteHash:String = MD5.hashBytes(fileBA); //Local hash
var ba_storageHash:ByteArray = new ByteArray();
ba_storageHash = Base64.decode(storageMetaData.md5Hash); //update ByteArray
var storageHash:String = bytesToHexString(ba_storageHash); //Hex values of bytes shown as String
trace("Network hash : " + storageMetaData.md5Hash); //bo7XPotC+T5wmAcpagnXBw==
trace("Local hash : " + byteHash); //93b885adfe0da089cdf634904fd59f71
trace("storage hash : " + storageHash); //what is result??
if (byteHash != storageHash)
{
trace("Not equal. Getting file."); //Always happens
getFile();
}
else
{
loadFile();
}
}
// # Byte values (Hex) shown as (returned) String type
private function bytesToHexString(input:ByteArray) : String
{
var strOut:String = ""; var strRead:String = "";
input.position = 0;
var intBASize:uint = input.length;
for (var i:int = 0; i < intBASize; i++)
{
strRead = input.readUnsignedByte().toString(16);
if(strRead.length < 2) { strRead = "0" + strRead; } //# do padding
strOut += strRead ;
}
return strOut.toLowerCase(); //strOut.toUpperCase();
}

Execute Code as Fast as Possible

I am using node.js with my WebStorm IDE to parse a large JSON file (~500 megabytes). Here is my code:
fs = require("fs");
fs.readFile('C:/Users/.../Documents/AAPL.json', 'utf8', function (err,data) {
for (i = 0; i < 1000; i++) {
var hex = JSON.parse(data)[i]._source.layers.data["data.data"];
var askPrice = parseInt(hex.substring(215, 239).split(":").reverse().join(""),16);
var bidPrice = parseInt(hex.substring(192, 215).split(":").reverse().join(""),16);
var symbol = hex.substring(156, 179);
var timestamp = hex.substring(132, 155);
var askSize = hex.substring(240, 251);
var bidSize = hex.substring(180, 191);
var price = String((+bidPrice+askPrice)/2);
var realprice = price.slice(0, price.length - 4) + "." + price.slice(price.length - 4);
function hex2a(hexx) {
var hex = hexx.toString();
var str = '';
for (var i = 0; i < hex.length; i += 2)
str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
return str;
}
if(JSON.parse(data)[i]._source.layers.data["data.len"] == 84 && realprice.length == 8 && +realprice <154 && +realprice >145) {
console.log(i + " " + hex2a(symbol.replace(/:/g, "")) + " sold for " + realprice + " at " + parseInt(timestamp.split(":").reverse().join(""), 16));
}
}
});
The problem I am running into however is that my IDE is parsing this file at an extremely slow speed, roughly 1 iteration a second. I do not think this is because I have a slow computer, for I have a high end rig with a core i7 7700k and a gtx 1070. I tried executing the code in the console with the same result. I tried trimming down the code and again I achieved the same speed:
fs = require("fs");
fs.readFile('C:/Users/Brandt Winkler Prins/Documents/AAPL.json', 'utf8', function (err,data) {
for (i = 0; i < 12000; i++) {
var hex = JSON.parse(data)[i]._source.layers.data["data.data"];
var askPrice = parseInt(hex.substring(215, 239).split(":").reverse().join(""),16);
var bidPrice = parseInt(hex.substring(192, 215).split(":").reverse().join(""),16);
var price = String((+bidPrice+askPrice)/2);
var realprice = price.slice(0, price.length - 4) + "." + price.slice(price.length - 4);
if(+realprice <154 && +realprice >145) {
console.log(realprice);
}
}
});
How should I execute my code to get my data as fast as possible?
You're running JSON.parse(data) every iteration, that might take quite some time for a 500MB json file.
The solution would be to move it out of the loop and reuse the parsed object:
var obj = JSON.parse(data);
for (...