Check SSL certificate Expiration Date - javascript

I need to check local computer's SSl certificate expiry DATE and compare it with current date and notify user that his/her certificate is going to expire in X days. All this I need to do in JavaScript.

Your certificate should look like this:
-----BEGIN CERTIFICATE-----
MIIGoDCCBIigAwIBAgIJAICRY3cWdgK1MA0GCSqGSIb3DQEBCwUAMIGeMQswCQYD
VQQGEwJCRzERMA8GA1UECAwIQnVsZ2FyaWExDjAMBgNVBAcMBVNvZmlhMQ8wDQYD
..
ud5Nja8+xycA/Jk7bSvB1jJjpc3oL0G9j0HOcxqQKd4e1IQXuss5V7FnQxSOVCq4
GVK0r3LkAxtl/EGmQC1DRlHAUWg=
-----END CERTIFICATE-----
You need to strip the -----BEGIN CERTIFICATE----- header and the -----END CERTIFICATE----- trailer from the certificate data, the rest is a Base64 encoded byte array.
You need to decode it to an array of bytes (in this example represented as array of number, where each number represents a byte - number between 0 and 255 inclusive).
That byte array is a DER encoded ASN.1 structure as defined in RFC-5280.
The below example will parse the content of the certificate after the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- traile has already been stripped.
Usage:
var pem =
"MIIGijCCBXKgAwIBAgIQEpI/gkvDS6idH2m2Zwn7ZzANBgkqhkiG9w0BAQsFADCB\n"
...
+"VQ+o34uWo7z19I8eXWSXN6P+Uj1OvHn8zNM1G/ddjQXBwMvzwwJEdVBhdK1uQw==\n";
var bytes = fromBase64(pem);
var validity = getValidity(bytes);
var notBefore = validity.notBefore;
var notAfter = validity.notAfter;
var now = new Date();
if ( notBefore.getTime() < now.getTime()
&& now.getTime() < notAfter.getTime())
{
// Certificate is withing its validity days
} else {
// Certificate is either not yet valid or has already expired.
}
Parsing:
var TYPE_INTEGER = 0x02;
var TYPE_SEQUENCE = 0x10;
var TYPE_UTC_TIME = 0x17;
var TYPE_GENERALIZED_TIME = 0x18;
function subArray(original, start, end) {
var subArr = [];
var index = 0;
for (var i = start; i < end; i++) {
subArr[index++] = original[i];
}
return subArr;
}
function getDigit(d) {
switch (d) {
default:
case 0x30: case '0': return 0;
case 0x31: case '1': return 1;
case 0x32: case '2': return 2;
case 0x33: case '3': return 3;
case 0x34: case '4': return 4;
case 0x35: case '5': return 5;
case 0x36: case '6': return 6;
case 0x37: case '7': return 7;
case 0x38: case '8': return 8;
case 0x39: case '9': return 9;
}
}
function enterTag(bytes, start, requiredTypes, name) {
if (start + 1 > bytes.length) {
throw new Error("Too short certificate input");
}
var typeByte = bytes[start ] & 0x0FF;
var lenByte = bytes[start +1] & 0x0FF;
var type = typeByte & 0x1F;
var len = lenByte;
var index = start + 2;
if (requiredTypes.length > 0 && requiredTypes.indexOf(type) == -1) {
throw new Error("Invalid type");
}
var lengthOfLength = 0;
if (len > 0x07F) {
lengthOfLength = len & 0x7F;
len = 0;
for (var i =0; i < lengthOfLength && index < bytes.length; i++) {
len = (len << 8 ) | (bytes[index] & 0x00FF);
index++;
}
}
if (index >= bytes.length) {
throw new Error("Too short certificate input");
}
return {index: index, type: type, length: len}
}
function processTag(bytes, start, requiredTypes, name) {
var result = enterTag(bytes, start, requiredTypes, name);
var index = result.index + result.length;
if (index >= bytes.length) {
throw new Error("Too short certificate input");
}
var valueStart = result.index;
var valueEnd = result.index + result.length;
var value = subArray(bytes, valueStart, valueEnd);
return { index: index, type: result.type, value: value};
}
function readDate(bytes, start, name) {
var date = new Date();
var result = processTag(bytes, start,
[TYPE_UTC_TIME, TYPE_GENERALIZED_TIME], name);
var index, year;
if (result.type == 0x17) { // UTCTime
if (result.value.length < 12) {
throw new Error("Invalid type");
}
var yearHigh = getDigit(result.value[0]);
var yearLow = getDigit(result.value[1]);
var year2Digits = (yearHigh * 10 ) + (yearLow)
if (year2Digits >= 50) {
year = 1900 + year2Digits;
} else {
year = 2000 + year2Digits;
}
index = 2;
} else if (result.type = 0x18) { // GeneralizedTime
if (result.value.length < 14) {
throw new Error("Invalid type");
}
var year1 = getDigit(result.value[0]);
var year2 = getDigit(result.value[1]);
var year3 = getDigit(result.value[2]);
var year4 = getDigit(result.value[3]);
year = (year1 * 1000) + (year2 * 100) + (year3*10) + year4;
index = 4;
}
var monthHigh = getDigit(result.value[index++]);
var monthLow = getDigit(result.value[index++]);
var dayHigh = getDigit(result.value[index++]);
var dayhLow = getDigit(result.value[index++]);
var hourHigh = getDigit(result.value[index++]);
var hourLow = getDigit(result.value[index++]);
var minuteHigh = getDigit(result.value[index++]);
var minuteLow = getDigit(result.value[index++]);
var secondHigh = getDigit(result.value[index++]);
var secondLow = getDigit(result.value[index]);
var month = (monthHigh * 10) + monthLow;
var day = (dayHigh * 10) + dayhLow;
var hour = (hourHigh * 10) + hourLow;
var minute = (minuteHigh * 10) + minuteLow;
var second = (secondHigh * 10) + secondLow;
if (month < 1 || month > 12) {
throw new Error("Invalid month");
}
if (day < 1 || day > 31) {
throw new Error("Invalid day");
}
if (hour < 0 || hour > 24) {
throw new Error("Invalid hour");
}
if (minute < 0 || minute > 59) {
throw new Error("Invalid minute");
}
if (second < 0 || second > 59) {
throw new Error("Invalid second ");
}
date.setUTCFullYear(year);
date.setUTCMonth(month-1);
date.setUTCDate(day);
date.setUTCHours(hour);
date.setUTCMinutes(minute);
date.setUTCSeconds(second);
return {
index: result.index,
type: result.type,
length: result.length,
value: result.value,
date: date
};
}
function getValidity(bytes) {
if (bytes == null || bytes.length <= 0) {
return null;
}
var index = 0;
index = enterTag(bytes, index, [TYPE_SEQUENCE], "Certificate").index;
index = enterTag(bytes, index, [TYPE_SEQUENCE], "TBSCertificate").index;
var result = processTag(bytes, index, [0x00, 0x02],
"Version or SerialNumber");
if (result.type == 0) {
index = result.index;
result = processTag(bytes, index, [TYPE_INTEGER], "SerialNumber")
}
index = result.index;
result = processTag(bytes, index, [TYPE_SEQUENCE],
"Signature AlgorithmIdentifier");
index = result.index;
result = processTag(bytes, index, [], "Issuer Name");
index = result.index;
index = enterTag(bytes, index, [TYPE_SEQUENCE], "Validity").index;
result = readDate(bytes, index, "Not Before");
var notBefore = result.date;
index = result.index;
result = readDate(bytes, index, "Not After");
var notAfter = result.date;
return {notBefore: notBefore, notAfter: notAfter};
}
function getNextBase64Chr(str, index, equalSignReceived, alpha) {
var chr = null;
var code = 0;
var padding = equalSignReceived;
while (index < str.length) {
chr = str.charAt(index);
if (chr == " " || chr == "\r" || chr == "\n" || chr == "\t") {
index++;
continue;
}
if (chr == "=") {
padding = true;
} else {
if (equalSignReceived) {
throw new Error("Invalid Base64 Endcoding.");
}
code = alpha.indexOf(chr);
if (code == -1) {
throw new Error("Invalid Base64 Encoding .");
}
}
break;
}
return { character: chr, code: code, padding: padding, nextIndex: ++index};
}
function fromBase64(str) {
var alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var value = [];
var index = 0;
var destIndex = 0;
var padding = false;
while (true) {
var first = getNextBase64Chr(str, index, padding, alpha);
var second = getNextBase64Chr(str, first .nextIndex, first .padding, alpha);
var third = getNextBase64Chr(str, second.nextIndex, second.padding, alpha);
var fourth = getNextBase64Chr(str, third .nextIndex, third .padding, alpha);
index = fourth.nextIndex;
padding = fourth.padding;
// ffffffss sssstttt ttffffff
var base64_first = first.code == null ? 0 : first.code;
var base64_second = second.code == null ? 0 : second.code;
var base64_third = third.code == null ? 0 : third.code;
var base64_fourth = fourth.code == null ? 0 : fourth.code;
var a = (( base64_first << 2 ) & 0xFC ) | ((base64_second >> 4) & 0x03);
var b = (( base64_second << 4 ) & 0xF0 ) | ((base64_third >> 2) & 0x0F);
var c = (( base64_third << 6 ) & 0xC0 ) | ((base64_fourth >> 0) & 0x3F);
value [destIndex++] = a;
if (!third.padding) {
value [destIndex++] = b;
} else {
break;
}
if (!fourth.padding) {
value [destIndex++] = c;
} else {
break;
}
if (index >= str.length) {
break;
}
}
return value;
}
Used resources:
A Layman's Guide to a Subset of ASN.1, BER, and DER
Encoding of ASN.1 UTC Time and GeneralizedTime
RFC-5280

The only available option so far is forge - https://github.com/digitalbazaar/forge/blob/master/README.md or some sort of custom extension for the client.
Client side does not know nothing about other than DOM elements thus it cannot inspect SSL layer.
More on this Within a web browser, is it possible for JavaScript to obtain information about the SSL Certificate being used for the current page?

This is not possible from the client, but you could do something like this with node / shell combo.
Assuming you have access to the server the cert is running on you could do something like this on the host:
var execSync = require('child_process').execSync
var cmd = "echo | openssl s_client -connect 127.0.0.1:443 2>/dev/null | openssl x509 -noout -dates"
var stdout = execSync(cmd).toString()
// "notBefore=Feb 16 15:33:00 2017 GMT\nnotAfter=May 17 15:33:00 2017 GMT"
From there you could parse the dates reported by stdout and write them to a public resource or json file so they are readable from the client, and from there do your date comparison.

Related

i receive data type Uint8Array from port serial how can i transfer to decimal value [ web serial port ] [duplicate]

I have some UTF-8 encoded data living in a range of Uint8Array elements in Javascript. Is there an efficient way to decode these out to a regular javascript string (I believe Javascript uses 16 bit Unicode)? I dont want to add one character at the time as the string concaternation would become to CPU intensive.
TextEncoder and TextDecoder from the Encoding standard, which is polyfilled by the stringencoding library, converts between strings and ArrayBuffers:
var uint8array = new TextEncoder().encode("someString");
var string = new TextDecoder().decode(uint8array);
This should work:
// http://www.onicos.com/staff/iz/amuse/javascript/expert/utf.txt
/* utf.js - UTF-8 <=> UTF-16 convertion
*
* Copyright (C) 1999 Masanao Izumo <iz#onicos.co.jp>
* Version: 1.0
* LastModified: Dec 25 1999
* This library is free. You can redistribute it and/or modify it.
*/
function Utf8ArrayToStr(array) {
var out, i, len, c;
var char2, char3;
out = "";
len = array.length;
i = 0;
while(i < len) {
c = array[i++];
switch(c >> 4)
{
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
// 0xxxxxxx
out += String.fromCharCode(c);
break;
case 12: case 13:
// 110x xxxx 10xx xxxx
char2 = array[i++];
out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
break;
case 14:
// 1110 xxxx 10xx xxxx 10xx xxxx
char2 = array[i++];
char3 = array[i++];
out += String.fromCharCode(((c & 0x0F) << 12) |
((char2 & 0x3F) << 6) |
((char3 & 0x3F) << 0));
break;
}
}
return out;
}
It's somewhat cleaner as the other solutions because it doesn't use any hacks nor depends on Browser JS functions, e.g. works also in other JS environments.
Check out the JSFiddle demo.
Also see the related questions: here and here
Here's what I use:
var str = String.fromCharCode.apply(null, uint8Arr);
In Node "Buffer instances are also Uint8Array instances", so buf.toString() works in this case.
In NodeJS, we have Buffers available, and string conversion with them is really easy. Better, it's easy to convert a Uint8Array to a Buffer. Try this code, it's worked for me in Node for basically any conversion involving Uint8Arrays:
let str = Buffer.from(uint8arr.buffer).toString();
We're just extracting the ArrayBuffer from the Uint8Array and then converting that to a proper NodeJS Buffer. Then we convert the Buffer to a string (you can throw in a hex or base64 encoding if you want).
If we want to convert back to a Uint8Array from a string, then we'd do this:
let uint8arr = new Uint8Array(Buffer.from(str));
Be aware that if you declared an encoding like base64 when converting to a string, then you'd have to use Buffer.from(str, "base64") if you used base64, or whatever other encoding you used.
This will not work in the browser without a module! NodeJS Buffers just don't exist in the browser, so this method won't work unless you add Buffer functionality to the browser. That's actually pretty easy to do though, just use a module like this, which is both small and fast!
Found in one of the Chrome sample applications, although this is meant for larger blocks of data where you're okay with an asynchronous conversion.
/**
* Converts an array buffer to a string
*
* #private
* #param {ArrayBuffer} buf The buffer to convert
* #param {Function} callback The function to call when conversion is complete
*/
function _arrayBufferToString(buf, callback) {
var bb = new Blob([new Uint8Array(buf)]);
var f = new FileReader();
f.onload = function(e) {
callback(e.target.result);
};
f.readAsText(bb);
}
The solution given by Albert works well as long as the provided function is invoked infrequently and is only used for arrays of modest size, otherwise it is egregiously inefficient. Here is an enhanced vanilla JavaScript solution that works for both Node and browsers and has the following advantages:
• Works efficiently for all octet array sizes
• Generates no intermediate throw-away strings
• Supports 4-byte characters on modern JS engines (otherwise "?" is substituted)
var utf8ArrayToStr = (function () {
var charCache = new Array(128); // Preallocate the cache for the common single byte chars
var charFromCodePt = String.fromCodePoint || String.fromCharCode;
var result = [];
return function (array) {
var codePt, byte1;
var buffLen = array.length;
result.length = 0;
for (var i = 0; i < buffLen;) {
byte1 = array[i++];
if (byte1 <= 0x7F) {
codePt = byte1;
} else if (byte1 <= 0xDF) {
codePt = ((byte1 & 0x1F) << 6) | (array[i++] & 0x3F);
} else if (byte1 <= 0xEF) {
codePt = ((byte1 & 0x0F) << 12) | ((array[i++] & 0x3F) << 6) | (array[i++] & 0x3F);
} else if (String.fromCodePoint) {
codePt = ((byte1 & 0x07) << 18) | ((array[i++] & 0x3F) << 12) | ((array[i++] & 0x3F) << 6) | (array[i++] & 0x3F);
} else {
codePt = 63; // Cannot convert four byte code points, so use "?" instead
i += 3;
}
result.push(charCache[codePt] || (charCache[codePt] = charFromCodePt(codePt)));
}
return result.join('');
};
})();
Uint8Array to String
let str = Buffer.from(key.secretKey).toString('base64');
String to Uint8Array
let uint8arr = new Uint8Array(Buffer.from(data,'base64'));
I was frustrated to see that people were not showing how to go both ways or showing that things work on none trivial UTF8 strings. I found a post on codereview.stackexchange.com that has some code that works well. I used it to turn ancient runes into bytes, to test some crypo on the bytes, then convert things back into a string. The working code is on github here. I renamed the methods for clarity:
// https://codereview.stackexchange.com/a/3589/75693
function bytesToSring(bytes) {
var chars = [];
for(var i = 0, n = bytes.length; i < n;) {
chars.push(((bytes[i++] & 0xff) << 8) | (bytes[i++] & 0xff));
}
return String.fromCharCode.apply(null, chars);
}
// https://codereview.stackexchange.com/a/3589/75693
function stringToBytes(str) {
var bytes = [];
for(var i = 0, n = str.length; i < n; i++) {
var char = str.charCodeAt(i);
bytes.push(char >>> 8, char & 0xFF);
}
return bytes;
}
The unit test uses this UTF-8 string:
// http://kermitproject.org/utf8.html
// From the Anglo-Saxon Rune Poem (Rune version)
const secretUtf8 = `ᚠᛇᚻ᛫ᛒᛦᚦ᛫ᚠᚱᚩᚠᚢᚱ᛫ᚠᛁᚱᚪ᛫ᚷᛖᚻᚹᛦᛚᚳᚢᛗ
ᛋᚳᛖᚪᛚ᛫ᚦᛖᚪᚻ᛫ᛗᚪᚾᚾᚪ᛫ᚷᛖᚻᚹᛦᛚᚳ᛫ᛗᛁᚳᛚᚢᚾ᛫ᚻᛦᛏ᛫ᛞᚫᛚᚪᚾ
ᚷᛁᚠ᛫ᚻᛖ᛫ᚹᛁᛚᛖ᛫ᚠᚩᚱ᛫ᛞᚱᛁᚻᛏᚾᛖ᛫ᛞᚩᛗᛖᛋ᛫ᚻᛚᛇᛏᚪᚾ᛬`;
Note that the string length is only 117 characters but the byte length, when encoded, is 234.
If I uncomment the console.log lines I can see that the string that is decoded is the same string that was encoded (with the bytes passed through Shamir's secret sharing algorithm!):
Do what #Sudhir said, and then to get a String out of the comma seperated list of numbers use:
for (var i=0; i<unitArr.byteLength; i++) {
myString += String.fromCharCode(unitArr[i])
}
This will give you the string you want,
if it's still relevant
If you can't use the TextDecoder API because it is not supported on IE:
You can use the FastestSmallestTextEncoderDecoder polyfill recommended by the Mozilla Developer Network website;
You can use this function also provided at the MDN website:
function utf8ArrayToString(aBytes) {
var sView = "";
for (var nPart, nLen = aBytes.length, nIdx = 0; nIdx < nLen; nIdx++) {
nPart = aBytes[nIdx];
sView += String.fromCharCode(
nPart > 251 && nPart < 254 && nIdx + 5 < nLen ? /* six bytes */
/* (nPart - 252 << 30) may be not so safe in ECMAScript! So...: */
(nPart - 252) * 1073741824 + (aBytes[++nIdx] - 128 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
: nPart > 247 && nPart < 252 && nIdx + 4 < nLen ? /* five bytes */
(nPart - 248 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
: nPart > 239 && nPart < 248 && nIdx + 3 < nLen ? /* four bytes */
(nPart - 240 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
: nPart > 223 && nPart < 240 && nIdx + 2 < nLen ? /* three bytes */
(nPart - 224 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
: nPart > 191 && nPart < 224 && nIdx + 1 < nLen ? /* two bytes */
(nPart - 192 << 6) + aBytes[++nIdx] - 128
: /* nPart < 127 ? */ /* one byte */
nPart
);
}
return sView;
}
let str = utf8ArrayToString([50,72,226,130,130,32,43,32,79,226,130,130,32,226,135,140,32,50,72,226,130,130,79]);
// Must show 2H₂ + O₂ ⇌ 2H₂O
console.log(str);
Try these functions,
var JsonToArray = function(json)
{
var str = JSON.stringify(json, null, 0);
var ret = new Uint8Array(str.length);
for (var i = 0; i < str.length; i++) {
ret[i] = str.charCodeAt(i);
}
return ret
};
var binArrayToJson = function(binArray)
{
var str = "";
for (var i = 0; i < binArray.length; i++) {
str += String.fromCharCode(parseInt(binArray[i]));
}
return JSON.parse(str)
}
source: https://gist.github.com/tomfa/706d10fed78c497731ac, kudos to Tomfa
I'm using this function, which works for me:
function uint8ArrayToBase64(data) {
return btoa(Array.from(data).map((c) => String.fromCharCode(c)).join(''));
}
For ES6 and UTF8 string
decodeURIComponent(escape(String.fromCharCode(...uint8arrData)))
By far the easiest way that has worked for me is:
//1. Create or fetch the Uint8Array to use in the example
const bufferArray = new Uint8Array([10, 10, 10])
//2. Turn the Uint8Array into a regular array
const array = Array.from(bufferArray);
//3. Stringify it (option A)
JSON.stringify(array);
//3. Stringify it (option B: uses #serdarsenay code snippet to decode each item in array)
let binArrayToString = function(binArray) {
let str = "";
for (let i = 0; i < binArray.length; i++) {
str += String.fromCharCode(parseInt(binArray[i]));
}
return str;
}
binArrayToString(array);
class UTF8{
static encode(str:string){return new UTF8().encode(str)}
static decode(data:Uint8Array){return new UTF8().decode(data)}
private EOF_byte:number = -1;
private EOF_code_point:number = -1;
private encoderError(code_point) {
console.error("UTF8 encoderError",code_point)
}
private decoderError(fatal, opt_code_point?):number {
if (fatal) console.error("UTF8 decoderError",opt_code_point)
return opt_code_point || 0xFFFD;
}
private inRange(a:number, min:number, max:number) {
return min <= a && a <= max;
}
private div(n:number, d:number) {
return Math.floor(n / d);
}
private stringToCodePoints(string:string) {
/** #type {Array.<number>} */
let cps = [];
// Based on http://www.w3.org/TR/WebIDL/#idl-DOMString
let i = 0, n = string.length;
while (i < string.length) {
let c = string.charCodeAt(i);
if (!this.inRange(c, 0xD800, 0xDFFF)) {
cps.push(c);
} else if (this.inRange(c, 0xDC00, 0xDFFF)) {
cps.push(0xFFFD);
} else { // (inRange(c, 0xD800, 0xDBFF))
if (i == n - 1) {
cps.push(0xFFFD);
} else {
let d = string.charCodeAt(i + 1);
if (this.inRange(d, 0xDC00, 0xDFFF)) {
let a = c & 0x3FF;
let b = d & 0x3FF;
i += 1;
cps.push(0x10000 + (a << 10) + b);
} else {
cps.push(0xFFFD);
}
}
}
i += 1;
}
return cps;
}
private encode(str:string):Uint8Array {
let pos:number = 0;
let codePoints = this.stringToCodePoints(str);
let outputBytes = [];
while (codePoints.length > pos) {
let code_point:number = codePoints[pos++];
if (this.inRange(code_point, 0xD800, 0xDFFF)) {
this.encoderError(code_point);
}
else if (this.inRange(code_point, 0x0000, 0x007f)) {
outputBytes.push(code_point);
} else {
let count = 0, offset = 0;
if (this.inRange(code_point, 0x0080, 0x07FF)) {
count = 1;
offset = 0xC0;
} else if (this.inRange(code_point, 0x0800, 0xFFFF)) {
count = 2;
offset = 0xE0;
} else if (this.inRange(code_point, 0x10000, 0x10FFFF)) {
count = 3;
offset = 0xF0;
}
outputBytes.push(this.div(code_point, Math.pow(64, count)) + offset);
while (count > 0) {
let temp = this.div(code_point, Math.pow(64, count - 1));
outputBytes.push(0x80 + (temp % 64));
count -= 1;
}
}
}
return new Uint8Array(outputBytes);
}
private decode(data:Uint8Array):string {
let fatal:boolean = false;
let pos:number = 0;
let result:string = "";
let code_point:number;
let utf8_code_point = 0;
let utf8_bytes_needed = 0;
let utf8_bytes_seen = 0;
let utf8_lower_boundary = 0;
while (data.length > pos) {
let _byte = data[pos++];
if (_byte == this.EOF_byte) {
if (utf8_bytes_needed != 0) {
code_point = this.decoderError(fatal);
} else {
code_point = this.EOF_code_point;
}
} else {
if (utf8_bytes_needed == 0) {
if (this.inRange(_byte, 0x00, 0x7F)) {
code_point = _byte;
} else {
if (this.inRange(_byte, 0xC2, 0xDF)) {
utf8_bytes_needed = 1;
utf8_lower_boundary = 0x80;
utf8_code_point = _byte - 0xC0;
} else if (this.inRange(_byte, 0xE0, 0xEF)) {
utf8_bytes_needed = 2;
utf8_lower_boundary = 0x800;
utf8_code_point = _byte - 0xE0;
} else if (this.inRange(_byte, 0xF0, 0xF4)) {
utf8_bytes_needed = 3;
utf8_lower_boundary = 0x10000;
utf8_code_point = _byte - 0xF0;
} else {
this.decoderError(fatal);
}
utf8_code_point = utf8_code_point * Math.pow(64, utf8_bytes_needed);
code_point = null;
}
} else if (!this.inRange(_byte, 0x80, 0xBF)) {
utf8_code_point = 0;
utf8_bytes_needed = 0;
utf8_bytes_seen = 0;
utf8_lower_boundary = 0;
pos--;
code_point = this.decoderError(fatal, _byte);
} else {
utf8_bytes_seen += 1;
utf8_code_point = utf8_code_point + (_byte - 0x80) * Math.pow(64, utf8_bytes_needed - utf8_bytes_seen);
if (utf8_bytes_seen !== utf8_bytes_needed) {
code_point = null;
} else {
let cp = utf8_code_point;
let lower_boundary = utf8_lower_boundary;
utf8_code_point = 0;
utf8_bytes_needed = 0;
utf8_bytes_seen = 0;
utf8_lower_boundary = 0;
if (this.inRange(cp, lower_boundary, 0x10FFFF) && !this.inRange(cp, 0xD800, 0xDFFF)) {
code_point = cp;
} else {
code_point = this.decoderError(fatal, _byte);
}
}
}
}
//Decode string
if (code_point !== null && code_point !== this.EOF_code_point) {
if (code_point <= 0xFFFF) {
if (code_point > 0)result += String.fromCharCode(code_point);
} else {
code_point -= 0x10000;
result += String.fromCharCode(0xD800 + ((code_point >> 10) & 0x3ff));
result += String.fromCharCode(0xDC00 + (code_point & 0x3ff));
}
}
}
return result;
}
`
Using base64 as the encoding format works quite well. This is how it was implemented for passing secrets via urls in Firefox Send. You will need the base64-js package. These are the functions from the Send source code:
const b64 = require("base64-js")
function arrayToB64(array) {
return b64.fromByteArray(array).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "")
}
function b64ToArray(str) {
return b64.toByteArray(str + "===".slice((str.length + 3) % 4))
}
With vanilla, browser side, recording from microphone, base64 functions worked for me (I had to implement an audio sending function to a chat).
const ui8a = new Uint8Array(e.target.result);
const string = btoa(ui8a);
const ui8a_2 = atob(string).split(',');
Full code now. Thanks to Bryan Jennings & breakspirit#py4u.net for the code.
https://medium.com/#bryanjenningz/how-to-record-and-play-audio-in-javascript-faa1b2b3e49b
https://www.py4u.net/discuss/282499
index.html
<html>
<head>
<title>Record Audio Test</title>
<meta name="encoding" charset="utf-8" />
</head>
<body>
<h1>Audio Recording Test</h1>
<script src="index.js"></script>
<button id="action" onclick="start()">Start</button>
<button id="stop" onclick="stop()">Stop</button>
<button id="play" onclick="play()">Listen</button>
</body>
</html>
index.js:
const recordAudio = () =>
new Promise(async resolve => {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const mediaRecorder = new MediaRecorder(stream);
const audioChunks = [];
mediaRecorder.addEventListener("dataavailable", event => {
audioChunks.push(event.data);
});
const start = () => mediaRecorder.start();
const stop = () =>
new Promise(resolve => {
mediaRecorder.addEventListener("stop", () => {
const audioBlob = new Blob(audioChunks);
const audioUrl = URL.createObjectURL(audioBlob);
const audio = new Audio(audioUrl);
const play = () => audio.play();
resolve({ audioBlob, audioUrl, play });
});
mediaRecorder.stop();
});
resolve({ start, stop });
});
let recorder = null;
let audio = null;
const sleep = time => new Promise(resolve => setTimeout(resolve, time));
const start = async () => {
recorder = await recordAudio();
recorder.start();
}
const stop = async () => {
audio = await recorder.stop();
read(audio.audioUrl);
}
const play = ()=> {
audio.play();
}
const read = (blobUrl)=> {
var xhr = new XMLHttpRequest;
xhr.responseType = 'blob';
xhr.onload = function() {
var recoveredBlob = xhr.response;
const reader = new FileReader();
// This fires after the blob has been read/loaded.
reader.addEventListener('loadend', (e) => {
const ui8a = new Uint8Array(e.target.result);
const string = btoa(ui8a);
const ui8a_2 = atob(string).split(',');
playByteArray(ui8a_2);
});
// Start reading the blob as text.
reader.readAsArrayBuffer(recoveredBlob);
};
// get the blob through blob url
xhr.open('GET', blobUrl);
xhr.send();
}
window.onload = init;
var context; // Audio context
var buf; // Audio buffer
function init() {
if (!window.AudioContext) {
if (!window.webkitAudioContext) {
alert("Your browser does not support any AudioContext and cannot play back this audio.");
return;
}
window.AudioContext = window.webkitAudioContext;
}
context = new AudioContext();
}
function playByteArray(byteArray) {
var arrayBuffer = new ArrayBuffer(byteArray.length);
var bufferView = new Uint8Array(arrayBuffer);
for (i = 0; i < byteArray.length; i++) {
bufferView[i] = byteArray[i];
}
context.decodeAudioData(arrayBuffer, function(buffer) {
buf = buffer;
play2();
});
}
// Play the loaded file
function play2() {
// Create a source node from the buffer
var source = context.createBufferSource();
source.buffer = buf;
// Connect to the final output node (the speakers)
source.connect(context.destination);
// Play immediately
source.start(0);
}
var decodedString = decodeURIComponent(escape(String.fromCharCode(...new Uint8Array(err))));
var obj = JSON.parse(decodedString);
I am using this Typescript snippet:
function UInt8ArrayToString(uInt8Array: Uint8Array): string
{
var s: string = "[";
for(var i: number = 0; i < uInt8Array.byteLength; i++)
{
if( i > 0 )
s += ", ";
s += uInt8Array[i];
}
s += "]";
return s;
}
Remove the type annotations if you need the JavaScript version.
Hope this helps!

Javascript String Manipulation and Conversion with Range

I have a string like this (must be in this format):
var string = "[0] No new notifications | [1,] Some new notifications"
And I want to get "No new notifications" if a variable is 0 and if that variable is 1 or greater, show "Some new notifications".
How can I do that?
Here's a generic processesor for ISO 31-11 strings. It takes the ISO 31-11 string and the numeric value, then returns the appropriate string or undefined. Here's a fiddle.
function processISO31_11(rangeGuide, n) {
var separator = /\[(\d+)(,)?(\d+)?\]\s?(.+)/;
var rangeGuides = rangeGuide.split('|');
var guideCount = rangeGuides.length;
for (var guide = 0; guide < guideCount; guide++) {
var elements = separator.exec(rangeGuides[guide]);
if (elements != null) {
if (n < parseFloat(elements[1])) {
return; // return undefined indicating failure to match any range
}
if (n == parseFloat(elements[1])) {
return elements[4];
}
if (elements[2] === "," && (typeof elements[3] === "undefined" || n <= parseFloat(elements[3]))) {
return elements[4];
}
}
}
}
var somevar = 3;
var yourString = '[0] No new notifications | [1,] Some new notifications';
var notification = yourString .split(' | ');
var message=(somevar == 0 ? notification[0].split('] ')[1] : notification[1].split('] ')[1]);
the var message has your needed output.
After examining more closely exactly what you are looking for, I have come up with a solution that will read in the rules you pass it and essentially turn that into logic that your program will follow. Here is a demo of how it would work:
var myVar = 3;
var myStr = '[0] No new notifications | [1,4] Some new notifications | [5,] Several new notifications';
var notificationRules = getRules(myStr);
function getRules(rulesString) {
return rulesString.split(' | ').map(function(rule) {
var startValue, endValue;
var values = rule.match(/\[\d*,?\d*\]/g)[0];
values = values.replace(/\[|\]/g, "").split(",");
startValue = values[0];
endValue = +values[1] === 0 ? Infinity : values[1];
return {
startValue: Number(startValue),
endValue: endValue != undefined ? Number(endValue) : undefined,
message: rule.replace(/\[\d*,?\d*\]/g, "").trim()
};
});
}
function getMessage(myVar, rules) {
var message = "No rule match!";
rules.some(function(rule) {
if (myVar === rule.startValue) {
message = rule.message;
return true;
} else if (myVar >= rule.startValue && myVar <= rule.endValue) {
message = rule.message;
}
});
return message;
}
console.log(getMessage(0, notificationRules));
console.log(getMessage(2, notificationRules));
console.log(getMessage(5, notificationRules));
console.log(getMessage(100, notificationRules));
console.log(getMessage(-1, notificationRules));
Complex solution using String.prototype.split(), String.prototype.match() and String.prototype.slice() functions:
var configStr = '[0] No new notifications | [1,] Some new notifications',
getNotifyMessage = function (config, num) {
var num = Number(num),
items = config.split('|'),
len = items.length, parts;
while (len--) {
parts = items[len].match(/\[(\d+,?)\]\s([\w ]+)(?=\||$)/i);
if (Number(parts[1]) === num) {
return parts[2];
}
if (parts[1].slice(-1) === ',' && Number(parts[1].slice(0,-1)) <= num) {
return parts[2];
}
}
return '';
};
console.log(getNotifyMessage(configStr, 1));
console.log(getNotifyMessage(configStr, 0));
console.log(getNotifyMessage(configStr, 3));

returning equation with all possible parenthesis combinations and the result of each

On a recent interview, I was asked to return all possible combinations of order of operations on an input string, and the result. you should return all the ways/combinations in which you can "force" operations with parenthesis. I got the result (right hand side of the equation) but got stuck on the left side. how could I have done the left side and the right hand side together? Seems like two problems in one...
//input:
console.log(diffWaysToCompute("2 * 3 - 4 * 5"));
//output:
(2*(3-(4*5))) = -34
((2*3)-(4*5)) = -14
((2*(3-4))*5) = -10
(2*((3-4)*5)) = -10
(((2*3)-4)*5) = 10
'use strict'
function getNumbersAndOperators(str) {
var arr = str.split(" ");
var operators = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] === "-" || arr[i] === "*" || arr[i] === "+") {
operators.push(arr[i]);
arr.splice(i, 1);
// console.log(operators);
}
}
return [arr, operators];
}
// console.log(getNumbersAndOperators("2 - 1 - 1"))
var diffWaysToCompute = function (input) {
// var numbers = input.split(" ");
// console.log(numbers);
// // console.log(number);
var results = compute(input);
results.sort(function (a, b) {
return a - b;
});
//put the numbers length into valid parenthesis:
var NumbersAndOperators = getNumbersAndOperators(input);
var numbers = NumbersAndOperators[0];
console.log(numbers);
var operators = NumbersAndOperators[1];
console.log(operators);
var parens = validParentheses(numbers.length);
// console.log(numbers);
console.log(operators);
// for (var i = 0; i < parens.length; i++) {
// for (var j = 0; j < parens[i].length; j++) {
// var val = parens[i][j];
// console.log(val);
// if (val === " ") {
// var num = numbers.shift();
// parens.splice(val, 0, num);
// //starting running into infinite loops and out of time.
// j--;
// }
// }
// i--;
// }
console.log(parens);
return results;
};
function validParentheses(n) {
if (n === 1) {
return ['( )'];
}
var prevParentheses = validParentheses(n - 1);
var list = {};
prevParentheses.forEach(function (item) {
list['( ' + item + ' )'] = null;
list['( )' + item] = null;
list[item + '( )'] = null;
});
console.log(Object.keys(list))
return Object.keys(list);
}
function compute(str) {
var res = [];
var i;
var j;
var k;
var left;
var right;
var string = [];
var placed = true;
if (!/[+*-]/.test(str)) { // + - *
return [parseInt(str)];
}
for (i = 0; i < str.length; i++) {
if (/\+|\-|\*/.test(str[i])) { // + - *
left = compute(str.substring(0, i));
right = compute(str.substring(i + 1, str.length));
for (j = 0; j < left.length; j++) {
for (k = 0; k < right.length; k++) {
if (str[i] === '+') {
res.push(parseInt(left[j] + right[k]));
} else if (str[i] === '-') {
// string.push("(" + str[i-2], str[i+2] + ")");
res.push(parseInt(left[j] - right[k]));
} else if (str[i] === '*') {
res.push(parseInt(left[j] * right[k]));
}
}
}
}
}
// console.log(string);
return res;
}
console.log(diffWaysToCompute("2 - 1 - 1"));
console.log(diffWaysToCompute("2 * 3 - 4 * 5"));
I never had to do such silly things, so let me try my teeth at it now.
(Caveat as always: it's highly simplified and without any checks&balances!)
The parser is the simplest thing here:
/*
Use of strings instead of ASCII codes for legibility.
I changed x - y to x + (-y) not only for convenience
but for algebraic correctness, too.
#param a array number nodes
#param o array operator nodes
*/
function parse(s,a,o){
var fnum = 0;
var uminus = false
for(var i=0;i<s.length;i++){
switch(s[i]){
case '-': uminus = true;
a.push(fnum);
o.push('+');
fnum = 0;
break;
case '+':
case '*':
case '/': if(uminus){
uminus = false;
fnum *= -1;
}
a.push(fnum);
o.push(s[i]);
fnum = 0;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9': fnum = fnum * 10 + parseInt(s[i]);
break;
default: break;
}
}
//assuming symmetry
a.push(fnum);
}
The (-generation took me some time, too much time--I cheated here ;-)
/*
Found in an old notebook (ported from C)
Algo. is O(n^2) and can be done faster but I
couldn't be a...ehm, had no time, sorry.
#idx int index into individual result
#n int number of groups
#open int number of opening parentheses
#close int number of closing parentheses
#a array individual result
#all array space for all results
*/
function makeParens(idx,n,open,close,a,all){
if(close == n){
all.push(a.slice(0));
return;
} else {
if(open > close){
a[idx] = ')';
makeParens(idx+1,n,open,close+1,a,all);
}
if(open < n){
a[idx] = '(';
makeParens(idx+1,n,open+1,close,a,all);
}
}
}
And now? Yepp, that took me a while:
/*
The interesting part
Not very optimized but working
#s string the equation
#return array nicely formatted result
*/
function parenthesing(s){
var nums = [];
var ops = [];
var all = [];
var parens = [];
// parse input into numbers and operators
parse(input,nums,ops);
/*
Rules:
1) out-most parentheses must be open in direction to center
e.g.: (1+2+3), 1+(2+3), 1+(2+3)+4
but not: 1)+(2+3)+(4
so: first parenthesis on the left side must be open and
the last parenthesis on the right side must be close
2) parentheses in direct neighborhood to a number must be
open in direction to the number (multiplication is
not mutual)
e.g.: 1+(2+3)+4, but not: 1+2(+3+4)
3) parentheses in direct neighborhood to an operator must be
closed in direction to the operator (multiplication is
not mutual)
e.g.: 1+(2+3)+4, but not: 1+2(+3+)4
*/
// build combinations separately not in-line
// it's already a mess, no need to add more
makeParens(0,nums.length,0,0,[],parens);
// You may take a look at the raw material here
// console.log(parens.join("\n"));
for(var i= 0;i<parens.length;i++){
var term = [];
// work on copies to reduce pointer juggling
var _ops = ops.slice(0);
var _nums = nums.slice(0);
for(var j=0;j<parens[i].length;j++){
if(parens[i][j] === '('){
term.push("(");
// rule 3
if(parens[i][j+1] === ')'){
term.push(_nums.shift());
}
// rules 1,2
else {
term.push(_nums.shift());
term.push(_ops.shift());
}
}
if(parens[i][j] === ')'){
term.push(")");
// rules 2,3
if(parens[i][j+1] !== ')')
term.push(_ops.shift());
}
}
// some pretty printing
term = term.join("");
// eval() because I didn't want to write a parser
// but if you need one...
all.push(term + " = " + eval(term));
}
return all;
}
I'm not sure if I would get hired with that abomination. Ah, to be honest: I doubt it.
But I hope it is at least a little bit helpful.
Yikes. That was tricky. Good challenge. I'm sure this could be cut way down, but it works. I used lodash and broke the various functions down to make it more flexible. Here's a jsfiddle:
https://jsfiddle.net/mckinleymedia/3e8g22Lk/8/
Oops - had to add parseInt to the addition so it doesn't add as strings.
/*
//input:
diffWaysToCompute("2 * 3 - 4 * 5");
//output:
(2*(3-(4*5))) = -34 - 2,1,0
((2*3)-(4*5)) = -14 - 0,2,1 & 2,0,1
((2*(3-4))*5) = -10 - 1,0,2
(2*((3-4)*5)) = -10 - 1,2,0
(((2*3)-4)*5) = 10 - 0,1,2
*/
'use strict'
var diffWaysToCompute = function(str) {
var opsAvailable = ['+','-','/','*'],
numbers = [],
operators = [],
getNumbersAndOperators = function(str) {
var arr = str.split(" ");
for (var i in arr) {
if ( opsAvailable.indexOf( arr[i] ) > -1 ) {
operators.push( arr[i] );
} else {
numbers.push( arr[i] );
}
};
return;
},
permutator = function(range) {
var results = [];
function permute(arr, memo) {
var cur,
memo = memo || [];
for (var i in arr) {
cur = arr.splice(i, 1);
if (arr.length === 0) results.push(memo.concat(cur));
permute(arr.slice(), memo.concat(cur));
arr.splice(i, 0, cur[0]);
}
return results;
}
return permute(_.range(range));
},
equations = function( perms ) {
var results = [];
_.each(perms, function( perm, k ) {
results[k] = nest ( perm );
});
return results;
},
nest = function( perm ) {
var eqs = eqs || [],
ref = ref || _.range(perm.length).map(function () { return undefined }),
eq,
target = undefined;
for (var i in perm) {
var cur = perm[i],
next = perm[i] + 1,
n1 = numbers[ cur ],
n2 = numbers[ next ],
r1 = ref[ cur ],
r2 = ref[ next ];
if ( r1 !== undefined) n1 = eqs [ r1 ];
if ( r2 !== undefined) n2 = eqs [ r2 ];
var rNew;
rNew = eqs.length;
for (var x in ref ) {
if ( ( ref[ x ] !== undefined ) && ( ref[ x ] == r1 || ref[ x ] == r2 ) ) ref[ x ] = eqs.length;
};
ref[ cur ] = ref[ next ] = eqs.length;
eqs.push({
ops: operators[ cur ],
nums: [ n1, n2 ]
});
};
return eqs[ eqs.length - 1 ];
},
calculations = function ( eqs ) {
var results = []
_.each(eqs, function(equation) {
results.push(calculate( equation ));
});
return results;
},
calculate = function( eq ) {
var result = {
text: ""
};
// result.eq = eq;
result.text += "( ";
result.total = eq.nums[ 0 ];
if ( _.isObject(result.total) ) {
var result1 = calculate( result.total );
result.total = result1.total;
result.text += result1.text;
} else {
result.text += eq.nums[ 0 ];
}
_.each(eq.ops, function (op, k) {
var num = eq.nums[ k + 1 ];
result.text += " " + op + " ";
if ( _.isObject(num) ) {
var result2 = calculate( num );
num = result2.total;
result.text += result2.text;
} else {
result.text += num;
}
if ( op === '+') result.total = parseInt(result.total) + parseInt(num);
if ( op === '-') result.total = result.total - num;
if ( op === '/') result.total = result.total / num;
if ( op === '*') result.total = result.total * num;
});
result.text += " )";
return result;
},
display = function( as ) {
var target = document.getElementById('result');
target.innerHTML += '<h3 class="problem">String given: ' + str + '</h3>';
target.innerHTML += '<h4>Permutations</h4>';
_.each( as, function(a) {
target.innerHTML += '<div class="permutation">';
target.innerHTML += ' <span class="formula">' + a.text + '</span> = ';
target.innerHTML += ' <span class="total">' + a.total + '</span>';
target.innerHTML += '</div>';
});
},
perms,
eqs,
answers;
getNumbersAndOperators(str);
perms = permutator( operators.length );
eqs = equations( perms );
answers = calculations( eqs );
answers = _.uniq(answers, 'text');
display(answers);
return answers;
};
console.log(diffWaysToCompute("2 * 3 - 4 * 5"));

How do you return the resulting object in a function?

Good day, all! :)
For the past month, I have been working on a function to return 2 or more THREE.js materials in 1 function at 1 time. I've run into a small problem though. For some reason, I can't get this function to return the MeshBasicMaterial object AS WELL AS the MeshLambertMaterial data object. I KNOW my code is right because I've gone over it over 40 times already looking for errors.
Here's the WHOLE code:
/**
* A function for converting hex <-> dec w/o loss of precision.
*
* The problem is that parseInt("0x12345...") isn't precise enough to convert
* 64-bit integers correctly.
*
* Internally, this uses arrays to encode decimal digits starting with the least
* significant:
* 8 = [8]
* 16 = [6, 1]
* 1024 = [4, 2, 0, 1]
*/
// Adds two arrays for the given base (10 or 16), returning the result.
// This turns out to be the only "primitive" operation we need.
function add(x, y, base)
{
var z = [];
var n = Math.max(x.length, y.length);
var carry = 0;
var i = 0;
while (i < n || carry)
{
var xi = i < x.length ? x[i] : 0;
var yi = i < y.length ? y[i] : 0;
var zi = carry + xi + yi;
z.push(zi % base);
carry = Math.floor(zi / base);
i++;
}
return z;
}
// Returns a*x, where x is an array of decimal digits and a is an ordinary
// JavaScript number. base is the number base of the array x.
function multiplyByNumber(num, x, base)
{
if (num < 0) return null;
if (num == 0) return [];
var result = [];
var power = x;
while (true)
{
if (num & 1)
{
result = add(result, power, base);
}
num = num >> 1;
if (num === 0) break;
power = add(power, power, base);
}
return result;
}
function parseToDigitsArray(str, base)
{
var digits = str.split('');
var ary = [];
for (var i = digits.length - 1; i >= 0; i--)
{
var n = parseInt(digits[i], base);
if (isNaN(n)) return null;
ary.push(n);
}
return ary;
}
function convertBase(str, fromBase, toBase)
{
var digits = parseToDigitsArray(str, fromBase);
if (digits === null) return null;
var outArray = [];
var power = [1];
for (var i = 0; i < digits.length; i++)
{
// invariant: at this point, fromBase^i = power
if (digits[i])
{
outArray = add(outArray, multiplyByNumber(digits[i], power, toBase), toBase);
}
power = multiplyByNumber(fromBase, power, toBase);
}
var out = '';
for (var i = outArray.length - 1; i >= 0; i--)
{
out += outArray[i].toString(toBase);
}
return out;
}
function decToHex(decStr) {
var hex = convertBase(decStr, 10, 16);
return hex ? '0x' + hex : null;
}
function hexToDec(hexStr) {
if (hexStr.substring(0, 2) === '0x') hexStr = hexStr.substring(2);
hexStr = hexStr.toLowerCase();
return convertBase(hexStr, 16, 10);
}
function instr(str, val)
{
if(typeof(str) === 'string')
{
str = str.toString(str);
val = val.toString(val);
in_str = str.indexOf(val);
return in_str;
}
else
{
api_messagebox('Please use a string!');
}
return false;
}
function Get_RGBA(hexVal, getwhich)
{
hexVal = hexVal || '';
getwhich = getwhich || 0;
var commaSeperated = 0;
//if(typeof(hexVal) === 'string')
//{
// Removes the first character from the input string
if(hexVal.length === 8) { hexVal = hexVal.substring(1, hexVal.length); }
if(hexVal.length === 10) { hexVal = hexVal.substring(0, hexVal.length); }
// Now let's separate the pairs by a comma
for (var i = 0; i <= hexVal.length; i++)
{
// Iterate through each char of hexVal
// Copy each char of hexVal to commaSeperated
commaSeperated += hexVal.charAt(i);
// After each pair of characters add a comma, unless this
// is the last char
commaSeperated += (i % 2 == 1 && i != (hexVal.length - 1)) ? ',' : '';
}
// Lets now remove the 0x
if(instr(commaSeperated, '0x'))
{
commaSeperated = commaSeperated.substr(4);
}
if(instr(commaSeperated, ','))
{
// Lets now remove all "," 's
commaSeperated = commaSeperated.replace(/,/g, '');
if( getwhich < 0 ) { getwhich = 0; }
if( getwhich > 5 ) { getwhich = 5; }
alpha = [];
red = [];
green = [];
blue = [];
allcol = [];
sixcol = [];
alpha[0] = commaSeperated[0]+commaSeperated[1];
red[0] = commaSeperated[2]+commaSeperated[3];
green[0] = commaSeperated[4]+commaSeperated[5];
blue[0] = commaSeperated[6]+commaSeperated[7];
allcol[0] = alpha[0]+red[0]+green[0]+blue[0];
sixcol[0] = red[0]+green[0]+blue[0];
if( getwhich === 0 ) { fi_string = alpha[0]; }
if( getwhich === 1 ) { fi_string = red[0]; }
if( getwhich === 2 ) { fi_string = green[0]; }
if( getwhich === 3 ) { fi_string = blue[0]; }
if( getwhich === 4 ) { fi_string = allcol[0]; }
if( getwhich === 5 ) { fi_string = sixcol[0]; }
if( getwhich === 4 && fi_string.length != 10 || fi_string.length != 9 ) { getwhich = 5; }
if( getwhich === 5 && fi_string.length != 8 || fi_string.length != 7 ) { getwhich = 4; }
// Split the commaSeperated string by commas and return the array
return fi_string.toString();
}
//}
}
function isArray(myArray)
{
return myArray.constructor.toString();
//myArray.constructor.toString().indexOf("Array") > -1;
}
//EntityMaterial(0, 0, 0xFF44CFFC, 1, 0xFF000000, 4, 4, 0, 1.0, 0.8, "LambertBasicMaterial", 1)
function EntityMaterial(ptex, side, color, wire, wirecolor, col_type, col_wire_type, shading, transparent, opacity, mat_type, overdraw)
{
ptex = ptex || 0;
side = side || 0;
color = color || 0xFF006400;
wire = wire || 0;
wirecolor = wirecolor || 0xFF006400;
col_type = col_type || 4;
col_wire_type = col_wire_type || 4;
shading = shading || false;
transparent = transparent || 0.0;
opacity = opacity || 1.0;
mat_type = mat_type || "BasicMaterial";
overdraw = overdraw || true;
color = decToHex(color.toString());
wirecolor = decToHex(wirecolor.toString());
var gRGBA1 = Get_RGBA(color, col_type);
var gRGBA2 = Get_RGBA(wirecolor, col_wire_type);
var mat = 0;
if(mat_type === 'BasicMaterial')
{
this.materials = new THREE.MeshBasicMaterial
(
{
color: parseInt(gRGBA1, 16)
}
)
}
else if(mat_type === 'LambertMaterial')
{
this.materials = new THREE.MeshLambertMaterial
(
{
color: parseInt(gRGBA2, 16),
opacity: opacity,
wireframe: wire,
transparent: transparent
}
)
}
else if(mat_type === 'LambertBasicMaterial')
{
//new empty array.. could also be written as this.materials = new Array();
this.materials = [];
var mats = this.materials;
var basicMat = new THREE.MeshBasicMaterial( { color: parseInt(gRGBA1, 16) } );
var lambertMat = new THREE.MeshLambertMaterial( { color: parseInt(gRGBA2, 16), opacity: opacity, wireframe: wire, transparent: transparent } );
mats.push(basicMat);
mats.push(lambertMat);
api_messagebox(mats);
return mats;
}
}
Thank you so much!
Sincerely,
~Mythros
Right, I finally got around to trying it out and it all runs well for me.
To make sure we don't have any differences in environments take a look at the fiddle I made and let me know if it works for you as expected or if there's any other problems you need help with:
JSFiddle of original code
Small changes:
commented out the
api_messagebox(mats)
as it's undefined.
added lots of log statements so check out the web console.
Edit
I fixed the color problem by using THree.js' Color object as follows:
var color = new THREE.Color("rgb(0,0,255)");
But you may be doing this somewhere as the GET_RGBA function you are calling seems to be missing from the code you gave me.
As to making it wiremesh, I checked the Lambert object and it definitely had wiremesh = 1 set.
Make sure that the wire var you're passing is actually set to true, I set it explicitly in this updated fiddle

How to convert json objectId to its string representaion in javascript

I would like to convert json representation of bson ObjectId returned from REST mongodb API to string
from: {"inc":1365419770,"machine":-856505582,"timeSecond":1375343587,"time":1375343587000,"new":false};
to: 51fa13e3ccf2c3125162a6fa
in the client side, so it will call other API using path params.
I just developed it, in case some one else is looking for the same functionality.
var ObjectIdStr = function (hexstr) {
this.timestamp ;
this.machine ;
this.increment ;
if (this.__proto__.constructor !== ObjectIdStr) {
return new ObjectIdStr(hexstr);
}
var isValid = function( s ){
if ( s == null )
return false;
len = s.length;
if ( len != 24 )
return false;
for ( i=0; i<len; i++ ){
c = s.charAt(i);
if ( c >= '0' && c <= '9' )
continue;
if ( c >= 'a' && c <= 'f' )
continue;
if ( c >= 'A' && c <= 'F' )
continue;
return false;
}
return true;
}
var fromHex = function(hex){
hex = parseInt(hex, 16);
if (hex > 0x80000000) {
hex = hex - 0xFFFFFFFF - 1;
}
return hex;
}
if ( ! isValid( hexstr ) )
throw "invalid ObjectId [" + s + "]" ;
this.timestamp = fromHex(hexstr.substring(0,8));
this.machine = fromHex(hexstr.substring(8,16));
this.increment = parseInt( hexstr.substring(16,24) , 16);
}
var ObjectId = function (json) {
this.timestamp = json.timeSecond;
this.machine = json.machine;
this.increment = json.inc;
if (this.__proto__.constructor !== ObjectId) {
return new ObjectId(json);
}
var hex = function(number){
if (number < 0) {
number = 0xFFFFFFFF + number + 1;
}
return number.toString(16).toLowerCase();
}
this.toString = function () {
var timestamp = hex(this.timestamp);
var machine = hex(this.machine);
var increment = hex(this.increment);
return '00000000'.substr(0, 6 - timestamp.length) + timestamp +
'00000000'.substr(0, 6 - machine.length) + machine +
'00000000'.substr(0, 6 - increment.length) + increment ;
};
};
function testme(){
var objJson = {"inc":1365419770,"machine":-856505582,"timeSecond":1375343587,"time":1375343587000,"new":false};
$("#ObjIdStr").html(ObjectId(objJson).toString());
obj = ObjectIdStr("51fa13e3ccf2c3125162a6fa")
$("#out").html( obj.increment + " " + obj.machine + " " + obj.timestamp)
}

Categories

Resources