Friday, April 13, 2007

JavaScript private Python style properties - yet another experiment

JavaScript constructors (call them classses if You prefere) have some problem with private parameters or private methods.

To use a private parameter You should simply use a variable without this as scope prefix
function MyConstructor(){
this.getPrivate = function(){
return private;
};
var private = "something";
};

It's simple and it works perfectly.
Any external scope could get directly private variable and You can know its value only calling getPrivate method.

var obj = new MyConstructor;
alert(obj.getPrivate());

The cool thing is that if You change externally returned value it will not be changed inside object too but please remember that if You change them and it's a generic object or an array, these changes will be valid inside object scope too (object and arrays are sent by reference, You need to clone or copy them before to return them externally).

Well, this is just a private parameters introduction and this is not useful if You write only using prototype or Class.create style, everything, in these cases, will be public (remember that).

The other "trick" to have a private method is to use internal scope (nested) constructor functions.
function MyConstructor(){

this.public = "something";

this.setPublicValue = function(what){
this.public = what;
setPrivateValue(what + private);
};

function setPrivateValue(what){
private = what;
};

var private = "something";
};

Well done, we have a public method and a private one ... but what should we do to have correct scope inside private methods too?
function MyConstructor(){

this.public = "something";

this.setPublicValue = function(what){
setValue("no " + what);
};

function setValue(what){
this.public = what;
};
};

Above code will not work because when You call a function without a dedicated scope, using for example apply or call, this will be just the global window object (super object).
We need to use call or apply, and problem is solved
function MyConstructor(){

this.public = "something";

this.setPublicValue = function(what){
setValue.call(this, "yes " + what);
};

function setValue(what){
this.public = what;
};
};
var o = new MyConstructor;
alert(o.public);
o.setPublicValue("now I can set them");
alert(o.public);



Well ... and what about choosed topic?
These examples shows that JavaScript constructors should have both private parameters and methods, but sometimes I think about other languages style and this is my experiment.
function MyConstructor(a,b,c){

this.getVar = function(){
return this.__privateVar;
};

this.setVar = function(){
this.__privateMethod("private var setted by a private method");
};

this.__privateVar = "private var";

this.__privateMethod = function(arg){
this.__privateVar = [arg, [a,b,c]].join("\n");
};
};

MyConstructor = MyConstructor.toPrivate();

var asd = new MyConstructor(1, {}, false);
alert(asd.__privateVar); // undefined !!!
alert(asd.getVar()); // private var
asd.setVar();
alert(asd.getVar());
// private var setted by a private method
// 1, [object Object], false

"Public" parameters and methods that use double underscore "__" as prefix are privates!
This means that You can just write without apply or call problems simply calling private variables or functions using this as scope prefix and "__" before real name.
You could even call two vars or methods in the same way, just add __ before private one.


How can we do it?
Using this stupid prototype:
Function.prototype.toPrivate = function(){
var c = "".concat(this),
o = new this,
v = [],
k;
for(k in o) {
if(k.substr(0,2) === "__") {
v.push("var ".concat(k, "=o.", k, ";"));
c = c.replace(new RegExp("\\bthis\\s*\\.\\s*(".concat(k, ")\\b"), "g"), "$1");
if(o[k] && o[k].constructor === Function)
c = c.replace(/\}\s*$/, k.concat("=(function(s,m){return function(){return m.apply(s,arguments)}})(this,", k, ");", "}"));
}
};
eval(v.join("").concat("c=", c));
c.prototype = this.prototype;
return c;
};

Seems horrible? Yes, it is :D

What about this proto limits?
Well, the first limit is that I suggest You to write private methods or parameters correctly, as I showed at the top of this post, because a code that use eval and works on constructor toString native or modified method isn't a cool way to solve private scope.
The second limit is that You need to remember to call toPrivate prototype.
There are probably other limits but as I wrote, this is just an experiment, I hope funny for your "JS dynamic investigation", bye :)

Thursday, April 12, 2007

JSON and JSONRequest

I've just updated last JSON JavaScript object adding a dependency on JSONError dedicated error object.

I've uploaded a new object too, called JSONRequest and based on Douglas Crockford proposal.

I successful tested both JSON and JSONRequest but last one probably need more debug to work perfectly.

JSONRequest object allows developer to do more than a single JSON interaction using a queue variable to block multiple request errors and to reduce server requests, performing each request only if precedent one is completed.

The usage is very simple and if You read "official" JSONRequest page You'll agree that everything was implemented, except for server specs.

Server side should check Content-Type, with this object always setted as application/jsonrequest.
For POST requests server side will recieve a JSONRequest key that will contain JSON Array or Object rappresentation encoded using encodeURIComponent.

Compatibility should be good enought, starting with IE 5.5 and if You have a personal encodeURIComponent top level function should run with IE5 too.

Opera, as FireFox and Safari should work correctly.
I'm waiting for your opinion about this object, I'm just using them but I'm not yet totally sure this respect perfectly Douglas Crockford idea so please tell me what's wrong or what doesn't work as expected, thank You :)

Where is the link? It's here ;)

Instant Update
I uploaded a packer version of these 4 objects too, about 4.6 Kb

Thursday, April 5, 2007

Working on eval solution ...

Sorry guys, I'm trying to solve the problem but it seems really hard to do.

I found a new way but I tested this piece of code:

Function.prototype.constructor = function(){
sendToMaliciousCode.apply(null, arguments);
return function(){};
};


and I noticed that it changes even (function(){}).constructor ... that's why constructor is not read only and it can't be deleted.

I hope I'll find a solution as soon as I can ... and please sorry for fakes solutions.



Update
I don't know if this piece of code should be useful or should resolve the problem ... I'm testing them but I can't crack them.

function safeEval(c){
var f = function(){},
m = "constructor";
if(new f[m]() instanceof f[m])
return new f[m]("", "return "+c)()
};

alert(
(function(c,f,m,u){f=function(){},m="constructor";return new f[m]() instanceof f[m]?new f[m]("","return "+c)():u})
("[1,2,3]")
);

This is a bit bigger than old version but seems to be safer because any prototype, constructor change or re-defined Function seems to be able to recieve data (in this case a simple "[1,2,3]" string).
Please tell me if You find a way to crack this solution, thank You!


Update - Damn, I had It under my nose but I didn't see them!!!
Trick showed above seems to be good but too much "strange" and uses too much bytes!
Here there's another version, based, this time, on typeof statement.

var safeEval = function(c){
var f = Function;
if(typeof new f() === "function")
return new f("","return "+c)();
};

alert(
(function(c,f,u){f=Function;return typeof new f()==="function"?new f("","return "+c)():u})
("[1,2,3]")
);


Why typeof statement?
JavaScript constructors are functions and every kind of constructor returns a typeof object.
Every instances require to use new and this is another keyword that You can't change!

What is the only constructor that returns a function and not an object?
The Function itself!!!


alert(typeof new WhatEverYouWant); // object

alert(typeof new Function); // function

It seems to be a valid solution for IE, FireFox and Opera, I need debug with Safari and other browsers, please tell me if You find a way to crack this other code, thank You again!


Update for XMLHttpRequest check
if((function(x,m,c,f,t){f=Function;if(typeof new f()===c){t=x[m];delete x[m];if(typeof new f("","return "+x)()!==c){x[m]=t;return 1}}})(XMLHttpRequest,"toString","function"))
alert("XMLHttpRequest is OK");
else
alert("XMLHttpRequest is Corrupted");

If typeof solution is not crackable, this one is safe too to know if original XMLHttpRequest object has been cracked.
Thank You again for debug and tests


Update - I forget last Array & Object security check
if((function(m){function $(c,t,f){f=Function;if(typeof new f()==="function"){t=c[m];delete c[m];try{new f("",c)}catch(e){c[m]=t;return 1}}};return $(Array)&&$(Object)})("toString"))
alert("I can decode a JSON string");
else
alert("JSON decoding is corrupted");


And this is my last proposal
json = "[1,2,3]";

result=(function(c,m,f){m="toString";f=Function;function $(c,t){if(typeof new f()==="function"){t=c[m];delete c[m];try{new f("",c)}catch(e){c[m]=t;return 1}}};if($(Array)&&$(Object))return new f("","return "+c)()})
(json);

alert(result);


This is an inline function that should solve Array and Object modified constructors problem returning a safe decoded json string.

It's about 220 bytes and this is the best security inline JSON decoding I thought, I hope this will be useful, not to solve JavaScript security problems but, at least, to solve eval, Array and Object paranoia.

Regards :)



Update - I cracked my solution

Function = (function(Functiold, Arrold, Objold){
function setArrayObject(){
Array = function(){
return new Arrold;
};
Array.toString = function(){
return ""+Arrold
};
Object = function(){
return new Objold;
};
Object.toString = function(){
return ""+Objold
};
f.toString = function(){
return ""+Functiold
};
};
var f = function(){
var a = arguments;
Functiold.prototype.constructor = Function;
Functiold.prototype.name = "anonymous";
setArrayObject();
delete Array.toString;
delete Object.toString;
if("" + a[1] === "" + Array)
a[1] = Arrold;
else if("" + a[1] === "" + Object)
a[1] = Objold;
setArrayObject();
return Functiold(a[0], a[1]);
};
setArrayObject();
return f;
})(Function, Array, Object);


It seems that first way is my last choice, using instanceof ... but probably I'll crack them too ... please stay tuned
This trick cracks first solution too.
At this point I'm going to do something else because it seems that there's no way with Internet Explorer, Opera and other browsers, to do a safe code evaluation.

With FireFox, You can delete eval and after that, use eval.
Bye