It easy if the code isn't minimized. but it's hard to tell apart minimized and obfuscated.
I've found this: http://research.microsoft.com/pubs/148514/tr.pdf
How would I detect the difference between minified and obfuscated code?
There isn't much to talk about here.
But first, lets ask a question: What is minimified code?
Well, that isn't too hard. Wikipedia has it! But doesn't explain how to achieve minified code.
Basically, you need to reduce your code as much as possible, but retain the same functionality.
Lets analize some code!
var times;
times = window.prompt('Insert a number','5');
times = parseInt( times, 10 );
if( !isNaN(times) )
{
for(var i=0; i<=10; i=i+1 )
{
document.write(times + ' × ' + i + ' = ' + ( i * times) + '<br/>');
}
}
else
{
alert('Invalid number');
}
Now, we can reduce that code a lot!
And that is what minifying is all about.
Now, lets look at this code:
var i=0,t=window.prompt('Insert a number',5);if(t/1==t/1)for(;i<11;i++)document.write(t+' × '+i+' = '+(i*t)+'<br/>');else alert('Invalid number');
It does exactly the same! But so much shorter!
What did I do:
Reduced the variable names
Declared them both at the same time
Reduced the number of times that a value is attributed to a variable
Replaced the string '5' with the number 5
Removed the unnecessary parseInt()
Replaced replaced !isNaN(times) with t/1==t/1
If it isn't a number, t/1 will be NaN.
If you run NaN==NaN, it will be false.
Removed whitespaces (spaced, newlines)
Removed braces
This code can be reduced even further, but you can (a little harder) see the functionality.
There are more techiniques to reduce the code size, but I won't go into detail.
But, now, another question: What is obfuscated code?
Obfuscated code is code that is incompreensible to us.
You can read the code, but the functionality won't be easily understood.
This goes a lot further than minifying. Reducing it's size isn't a requirement.
But, most of the time, the obfuscated code is reduced in a way you wouldn't understand.
Only those who know will be able to understand it.
JSF*ck is an example of this.
Using 2 online tools, here is what obfuscated code would look like:
Obfuscated using http://www.jsobfuscate.com/ :
eval(function(p,a,c,k,e,d){e=function(c){return c.toString(36)};if(!''.replace(/^/,String)){while(c--){d[c.toString(a)]=k[c]||c.toString(a)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('4 2;2=d.e(\'c a 3\',\'5\');2=b(2,6);7(!8(2)){9(4 i=0;i<=6;i=i+1){h.j(2+\' &2; \'+i+\' = \'+(i*2)+\'<f/>\')}}k{l(\'g 3\')}',22,22,'||times|number|var||10|if|isNaN|for||parseInt|Insert|window|prompt|br|Invalid|document||write|else|alert'.split('|'),0,{}))
Obfuscated using http://packer.50x.eu/ :
eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(c/a))+String.fromCharCode(c%a+161)};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\[\xa1-\xff]+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp(e(c),'g'),k[c])}}return p}('£ ¡;¡=©.¨(\'§ a ¢\',\'5\');¡=¥(¡,¤);¦(!ª(¡)){«(£ i=0;i<=¤;i=i+1){®.¬(¡+\' &¡; \'+i+\' = \'+(i*¡)+\'<±/>\')}}{¯(\'° ¢\')}',17,17,'times|number|var|10|parseInt|if|Insert|prompt|window|isNaN|for|write|else|document|alert|Invalid|br'.split('|'),0,{}))
Using those tools, there are a few similarities:
Both have an eval()
Both create a function with the variables p,a,c,k,e,d.
Both have a list of all the proterties and other stuff at the end
Both use string voodoo to generate the code
But is every obfuscated code equal? NO! It isn't.
Here is an example:
var ________________ = [] + []; var _ = +[]; _++; var _____ = _ + _;
var ___ = _____ + _____; var __ = ___ + ___; var ____ = __ + __; var ______ = ____ + ____;
var _______ = ______ + _; var ___________ = ______ + ______ + __;
var ______________ = ___________ + ____ - _; var ____________ = _ + _____;
var ________ = _______ * ____________ + _; var _________ = ________ + _;
var _____________ = ______________ + ______ - ___ - _; var __________ = _____________ -
____________; var _______________ = __________ - ____________; document.write(________________ +
String.fromCharCode(___________, _________, _______________, _______________, __________,
______, ______________, __________, _____________, _______________, ________, _______));
This was taken from another website. You can view the original answer here: https://codegolf.stackexchange.com/a/22746/14732
How do you tell this apart?
You simply can't. Or you are a super genius who can see an obfuscated code ans see what it does.
You would need a really smart algorithm to know what the code does. And then rebuild it backwards.
If both codes arent the same, then it may be obfuscated.
Conclusion: you can't tell apart an obfuscated code and a minified one.
Related
What do you think about using looooooong regular expressions? Does this affect performance?
This is one of my regular expressions: (blockquote messed it up, so I edited it)
([(]((((-?((([0-9]+)|([(]-[0-9]+[)]))|(([0-9]*i)|([(]-[0-9]*i[)])))[*/]((([0-9]*i)|([(]-[0-9]*i[)]))|(([0-9]+)|([(]-[0-9]+[)]))))|(-?(([0-9]+)|([(]-[0-9]+[)]))[+-](([0-9]*i)|([(]-[0-9]*i[)]))[+-]((([0-9]*i)|([(]-[0-9]*i[)]))|(([0-9]+)|([(]-[0-9]+[)]))))|([(]((-?(([0-9]+)|([(]-[0-9]+[)]))[+-](([0-9]*i)|([(]-[0-9]*i[)])))|(-?(([0-9]*i)|([(]-[0-9]*i[)]))[+-](([0-9]+)|([(]-[0-9]+[)]))))[)][+/*-]([(]((-?(([0-9]+)|([(]-[0-9]+[)]))[+-](([0-9]*i)|([(]-[0-9]*i[)])))|(-?(([0-9]*i)|([(]-[0-9]*i[)]))[+-](([0-9]+)|([(]-[0-9]+[)]))))[)]|(([0-9]*i)|([(]-[0-9]*i[)]))|(([0-9]+)|([(]-[0-9]+[)]))))|(-?(([0-9]*i)|([(]-[0-9]*i[)]))[+/*-]((([0-9]*i)|([(]-[0-9]*i[)]))|[(]((-?(([0-9]+)|([(]-[0-9]+[)]))[+-](([0-9]*i)|([(]-[0-9]*i[)])))|(-?(([0-9]*i)|([(]-[0-9]*i[)]))[+-](([0-9]+)|([(]-[0-9]+[)]))))[)]))|(-?(([0-9]+)|([(]-[0-9]+[)]))[+/*-]((([0-9]+)|([(]-[0-9]+[)]))|[(]((-?(([0-9]+)|([(]-[0-9]+[)]))[+-](([0-9]*i)|([(]-[0-9]*i[)])))|(-?(([0-9]*i)|([(]-[0-9]*i[)]))[+-](([0-9]+)|([(]-[0-9]+[)]))))[)])))([+/*-](((-?((([0-9]+)|([(]-[0-9]+[)]))|(([0-9]*i)|([(]-[0-9]*i[)])))[*/]((([0-9]*i)|([(]-[0-9]*i[)]))|(([0-9]+)|([(]-[0-9]+[)]))))|(-?(([0-9]+)|([(]-[0-9]+[)]))[+-](([0-9]*i)|([(]-[0-9]*i[)]))[+-]((([0-9]*i)|([(]-[0-9]*i[)]))|(([0-9]+)|([(]-[0-9]+[)]))))|([(]((-?(([0-9]+)|([(]-[0-9]+[)]))[+-](([0-9]*i)|([(]-[0-9]*i[)])))|(-?(([0-9]*i)|([(]-[0-9]*i[)]))[+-](([0-9]+)|([(]-[0-9]+[)]))))[)][+/*-]([(]((-?(([0-9]+)|([(]-[0-9]+[)]))[+-](([0-9]*i)|([(]-[0-9]*i[)])))|(-?(([0-9]*i)|([(]-[0-9]*i[)]))[+-](([0-9]+)|([(]-[0-9]+[)]))))[)]|(([0-9]*i)|([(]-[0-9]*i[)]))|(([0-9]+)|([(]-[0-9]+[)]))))|(-?(([0-9]*i)|([(]-[0-9]*i[)]))[+/*-]((([0-9]*i)|([(]-[0-9]*i[)]))|[(]((-?(([0-9]+)|([(]-[0-9]+[)]))[+-](([0-9]*i)|([(]-[0-9]*i[)])))|(-?(([0-9]*i)|([(]-[0-9]*i[)]))[+-](([0-9]+)|([(]-[0-9]+[)]))))[)]))|(-?(([0-9]+)|([(]-[0-9]+[)]))[+/*-]((([0-9]+)|([(]-[0-9]+[)]))|[(]((-?(([0-9]+)|([(]-[0-9]+[)]))[+-](([0-9]*i)|([(]-[0-9]*i[)])))|(-?(([0-9]*i)|([(]-[0-9]*i[)]))[+-](([0-9]+)|([(]-[0-9]+[)]))))[)])))|(([0-9]*i)|([(]-[0-9]*i[)]))|(([0-9]+)|([(]-[0-9]+[)]))|[(]((-?(([0-9]+)|([(]-[0-9]+[)]))[+-](([0-9]*i)|([(]-[0-9]*i[)])))|(-?(([0-9]*i)|([(]-[0-9]*i[)]))[+-](([0-9]+)|([(]-[0-9]+[)]))))[)]))*)|(((([0-9]*i)|([(]-[0-9]*i[)]))|(([0-9]+)|([(]-[0-9]+[)]))|[(]((-?(([0-9]+)|([(]-[0-9]+[)]))[+-](([0-9]*i)|([(]-[0-9]*i[)])))|(-?(([0-9]*i)|([(]-[0-9]*i[)]))[+-](([0-9]+)|([(]-[0-9]+[)]))))[)])([+/*-]((-?((([0-9]+)|([(]-[0-9]+[)]))|(([0-9]*i)|([(]-[0-9]*i[)])))[*/]((([0-9]*i)|([(]-[0-9]*i[)]))|(([0-9]+)|([(]-[0-9]+[)]))))|(-?(([0-9]+)|([(]-[0-9]+[)]))[+-](([0-9]*i)|([(]-[0-9]*i[)]))[+-]((([0-9]*i)|([(]-[0-9]*i[)]))|(([0-9]+)|([(]-[0-9]+[)]))))|([(]((-?(([0-9]+)|([(]-[0-9]+[)]))[+-](([0-9]*i)|([(]-[0-9]*i[)])))|(-?(([0-9]*i)|([(]-[0-9]*i[)]))[+-](([0-9]+)|([(]-[0-9]+[)]))))[)][+/*-]([(]((-?(([0-9]+)|([(]-[0-9]+[)]))[+-](([0-9]*i)|([(]-[0-9]*i[)])))|(-?(([0-9]*i)|([(]-[0-9]*i[)]))[+-](([0-9]+)|([(]-[0-9]+[)]))))[)]|(([0-9]*i)|([(]-[0-9]*i[)]))|(([0-9]+)|([(]-[0-9]+[)]))))|(-?(([0-9]*i)|([(]-[0-9]*i[)]))[+/*-]((([0-9]*i)|([(]-[0-9]*i[)]))|[(]((-?(([0-9]+)|([(]-[0-9]+[)]))[+-](([0-9]*i)|([(]-[0-9]*i[)])))|(-?(([0-9]*i)|([(]-[0-9]*i[)]))[+-](([0-9]+)|([(]-[0-9]+[)]))))[)]))|(-?(([0-9]+)|([(]-[0-9]+[)]))[+/*-]((([0-9]+)|([(]-[0-9]+[)]))|[(]((-?(([0-9]+)|([(]-[0-9]+[)]))[+-](([0-9]*i)|([(]-[0-9]*i[)])))|(-?(([0-9]*i)|([(]-[0-9]*i[)]))[+-](([0-9]+)|([(]-[0-9]+[)]))))[)]))))+))[)])
Can i use RegExp this length or is it bad practise?
EDIT
I'm constructing complex number calculator. This regex is made from shorter ones. This is how i am doing it:
var regularExpression = new (function()
{
this.re = "(([0-9]+)|([(]-[0-9]+[)]))",
this.im = "(([0-9]*i)|([(]-[0-9]*i[)]))",
this.complexNumber = "[(]((-?"+ this.re + "[+-]" + this.im + ")|(-?" + this.im + "[+-]" + this.re +"))[)]",
this.expression = "("+
"(-?("+this.re+"|"+this.im+")[*/]("+this.im+"|"+this.re+"))|"+
"(-?"+this.re+"[+-]"+this.im+"[+-]("+this.im+"|"+this.re+"))|"+
"("+this.complexNumber+"[+/*-]("+this.complexNumber+"|"+this.im+"|"+this.re+"))|"+
"(-?"+this.im+"[+/*-](" + this.im+"|"+this.complexNumber+"))|"+
"(-?"+this.re+"[+/*-](" + this.re+"|"+this.complexNumber+"))"+
")",
this.simpleExpression = "([(]("+
"("+this.expression+"([+/*-]("+this.expression+"|"+this.im+"|"+this.re+"|"+this.complexNumber+"))*)|"+
"(("+this.im+"|"+this.re+"|"+this.complexNumber+")([+/*-]"+this.expression+")+)"+
")[)])"
})();
So my regularExpression.simpleExpression is even longer, because is uses expression few times. Thats why I'm asking and worried.
simpleExpression is looking for strings like: (12321-12231i+1233123*(12i-231)+12323-i)
Regular expressions are very fast, when they are written in a good manner (definitely much faster than e.g. the code based on conditionals).
However, the question you should ask yourself is whether the code is maintainable and readable - someone may have to rewrite this part of the code in the future and even you might not understand it at first glance after some time.
First point from here might answer your question: https://hackernoon.com/few-simple-rules-for-good-coding-my-15-years-experience-96cb29d4acd9
What's the best way to do insert variables in a string in JavaScript? I'm guessing it's not this:
var coordinates = "x: " + x + ", y: " + y;
In Java, Strings are immutable and doing something like the above would unnecessarily create and throw away Strings. Ruby is similar and has a nice way of doing the above:
coordinates = "x: #{x}, y: #{y}"
Does something similar exist for JavaScript?
Introduced in ES6 as "template strings"
MDN docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
const name = "Nick"
const greeting = `Hello ${name}` // "Hello Nick"
That's fine in JavaScript. There is no good built-in equivalent of an sprintf or String.format, however, you can build your own.
Don't worry about the "unnecessary" string objects. That's definitely micro-optimization. Address it if and when you need that extra tiny bit of performance or memory optimization, but in distributed software, you probably don't.
https://www.npmjs.com/package/stringinject
https://github.com/tjcafferkey/stringinject
I created this function to do exactly this, it will allow you to pass in a string, and an object with keys that will replace placeholder values in the string with their values like below:
var str = stringInject("My username is {username} on {platform}", { username: "tjcafferkey", platform: "GitHub" });
// My username is tjcafferkey on Github
If for some reason you are doing this many times per second and referencing the strings many times per call, you can always store the strings themselves as variables.
var preX = 'x: '
, preY = 'y: '
, coords
;
coords = preX + x + preY + y;
This of course should be supported by benchmarking/profiling, but creating many strings per frame is often a source of unnecessary garbage which can result in jank down the line.
I have a number which currently is 1,657,108,700 and growing. However I wish for it to show as
1,657,108k
Does javascript or html have a build in function to do this?
The value is being set throu javascript to a span field in html.
[edit]
From the comment I got my method as far as:
var start = '1,657,108,700';
start = (start / 1000).toFixed(0);
var finish = '';
while (start.length > 3)
{
finish = ','.concat(start.substring(start.length - 3, 3), finish);
start = start.substring(0, start.length - 3);
};
finish = start + finish + "k";
return finish;
however this returns 1,65,7k instead of 1,657,108k.. anyone know why?
var formattedNumber = Math.round(yourNumber / 1000).toLocaleString() + "k";
Turn the above into a function or not as appropriate. I'm not aware of a single function to do this, or of a way to cater for non-English versions of "k" (assuming there are some), but at least toLocaleString() should take care of the comma versus fullstop for thousands issue.
UPDATE: I posted the above without testing it; when I tried it out I found toLocaleString() formatted 1234 as 1,234.00. I had thought of fixing it by using a regex replace to remove trailing zeros except of course I can't be sure what character toLocaleString() is going to use for the decimal point, so that won't work. I guess you could write some code that uses toLocaleString() on a "control" number (e.g., 1.1) to see at runtime what character it uses for the decimal.
UPDATE 2 for your updated question, inserting the commas manually, I did it like this:
var unformattedNumber = 123456;
var a = unformattedNumber.toString().split("");
for (var i=a.length-3; i >0; i-=3)
a.splice(i,0,",");
var formattedNumber = a.join("") + "k";
I'm creating a GreaseMonkey script to improve the user interface of the 10k tools Stack Overflow uses. I have encountered an unreproducible and frankly bizarre problem that has confounded me and the others in the JavaScript room on SO Chat. We have yet to find the cause after several lengthy debugging sessions.
The problematic script can be found here. Source - Install
The problem occurs at line 85, the line after the 'vodoo' comment:
return (t + ' (' + +(+f.offensive + +f.spam) + ')');
It might look a little weird, but the + in front of the two variables and the inner bracket is for type coercion, the inner middle + is for addition, and the other ones are for concatenation.
Nothing special, but observant reader might note that type coercion on the inner bracket is unnecessary, since both are already type coerced to numbers, and type coercing result is useless when they get concatenated into a string anyway. Not so! Removing the + breaks the script, causing f.offensive and f.spam to be concatenated instead of added together.
Adding further console.log only makes things more confusing:
console.log(f.offensive + f.spam); // 50
console.log('' + (+f.offensive + +f.spam)); // 5, but returning this yields 50 somehow
console.log('' + (+f.offensive + +f.spam) + ''); // 50
Source: https://chat.stackoverflow.com/transcript/message/203261#203261
The problem is that this is unreproducible - running scripts like
console.log('a' + (+'3' + +'1') + 'b');
in the Firebug console yields the correct result, as does
(function(){
return 'a' + (+'3' + +'1') + 'b';
})();
Even pulling out large chunks of the code and running them in the console does not reproduce this bug:
$('.post-menu a[id^=flag-post-]').each(function(){
var f = {offensive: '4', spam: '1'};
if(f){
$(this).text(function(i, t){
// Vodoo - please do not remove the '+' in front of the inner bracket
return (t + ' (' + +(+f.offensive + +f.spam) + ')');
});
}
});
Tim Stone in the chatroom has reproduction instruction for those who are below 10k.
This bug only appears in Firefox - Chrome does not appear to exhibit this problem, leading me to believe that this may be a problem with either Firefox's JavaScript engine, or the Greasemonkey add-on. Am I right?
I can be found in the JavaScript room if you want more detail and/or want to discuss this.
As part of the userscript's process, a <script> tag is injected into the page with the code retrieved by calling toString() on the function you've defined. Usually this would be fine, but it appears that there's a bug in the javascript engine used by Firefox 3.6.13 that relocates the parentheses in the expression, causing it to be evaluated in a very different way when the toString()-ified function is processed.
To illustrate this problem, we can run the following code in Firebug:
function f() { var a = '', b = '1', c = '2'; return a + '(' + (+b + +c) + ')'; };
f.toString();
This gives us this output:
function f() {
var a = "", b = "1", c = "2";
return a + ("(" + + b + + c + ")");
}
You'll note that the return expression has been modified. The parentheses have been relocated beyond the strings that were previously outside of them, causing the variables b and c to be coerced to strings and concatenated. This gives an unexpected result, since the expected addition never takes place. Unfortunately, this behaviour is present even when using Number() or parseInt() to coerce b and c.
There are several small modifications which change this, but the clearest is simply to save the result of the addition to a variable beforehand:
$(this).text(function(i, t){
var c = +f.offensive + +f.spam;
return (t + ' (' + c + ')');
});
Thankfully, this problem seems to not occur in the Firefox 4 beta, so hopefully this issue has been resolved going forward. Also, Matthew Flaschen has graciously gone ahead and filed a bug report (marked duplicate of 559438) so that the developers are made aware of this issue in either case.
I have a page with lots of big number values. Millions and billions of dollars going everywhere. And it is hard to read these numbers, so my client asks me to break them into more readable chunks of three symbols, "$100000000" => "$100 000 000".
This is completely reasonable request, but the problem is that I do not want to do this on server-side, and I do not want to do this with javascript. You see, I have a really big heap of javascript already running on this page, doing complex computations on these long numbers, and it will be really difficult to insert a parseReadableStringToInteger() in every place that reads data from page and a writeIntegerAsReadableString() in every place that writes results back to page.
So, I am thinking of using CSS to make long string display as a set of short chunks. My first thought was of -moz-column and -webkit-column, but unfortunately, they work only with words that are already separated by space.
Maybe there is another way? Any suggestions are welcome.
p.s. Cross-browser compatibility is not required. I'm ok with Gecko and/or Webkit.
There is no way to do it via CSS, but you can extend Number type like this:
Number.prototype.formatMoney = function(c, d, t){
var n = this, c = isNaN(c = Math.abs(c)) ? 2 : c, d = d == undefined ? "," : d, t = t == undefined ? "." : t, s = n < 0 ? "-" : "", i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "", j = (j = i.length) > 3 ? j % 3 : 0;
return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
};
then use it like this:
var count = 10000000;
count.formatMoney(2, '.', ' ')
Damn it, I'm almost there!!
span {
display: block;
-moz-column-gap:5px;
-moz-column-width:24px;
word-wrap:break-word;
}
<span>100000</span>
<span>1000000</span>
<span>10000000</span>
<span>100000000</span>
gives me
100 000
100 000 0
100 000 00
100 000 000
The only thing that is left is somehow start the splitting from the right. Now experimenting with direction: rtl and such :)
You're going to have to find a JavaScript way to do this, I'm pretty certain. Any CSS technique, even if it were possible, wouldn't be cross-browser.
If you aren't willing to use JavaScript to change the formatting, you should change their format from the server...ie, before rendering the page.
Here is a suggestion that would work, although even I will admit it isn't very nice...
Using the jQuery framework, $("#myElement").text() returns just the text (not any nested html). So you could do this:
<p>$<span id="myElement"><span class="triad">1</span><span class="triad">000</span><span class="triad">000</span></p>
And apply some padding or margin to make it more readable.
When you then call:
$("#myElement").text();
You would get the plain 1000000 back.
CSS:
.triad { padding-left: 5px; }
n1313, http://wiki.csswg.org/ideas/content-formatting ;) it's not a solution, just idea
function largeNumberToReadableNumber(number){
var str = Math.floor(amount)+""; //make the integer a string
var sub = str.substring(str.length-3, str.length); //the last three characters
newstr = " "+sub;
var i = 1;
while (sub.length >= 3){
sub = str.substring(str.length-((i+1)*3),str.length-(i*3)); //next three characters
newstr = sub + " " + newstr; //append the characters
i+=1;
}
return newstr;
}
largeNumberToReadable(120312381124124); //will output " 120 312 381 124 124"
I am sure this can be written better and shorter but it does the job.
I found this piece of javascript which might help you out if you are going to do it client-side:
http://homepage.mac.com/ruske/ruske/C2127905073/E844527267/Media/FormatInteger.js
No CSS manipulates strings. Sry you'll have to do it with JS
How about having the number twice: Once for displaying and once for manipulation like this:
<span class="money" data-value="1000000">$ 1 000 000</span>
Then you can easly use getAttribute('data-value') to get to the value from your JS and format the number any way you want.
data-* attributes are a new feature in HTML 5, but pretty much all current browsers already support it (modulu the .dataset property in the DOM, so you'll have to use getAttribute() in current/older browsers).
I wish this was possible with CSS :( you can not get text value and use that in later operations using CSS.
The first thing that comes to mind is using :after and :before with content:" "
Then you just need something that dynamically add a tag around the right numbers and style it.