How to make injected js execute?

P

Peter Michaux

Randy Webb said the following on 8/20/2007 8:46 PM:

I have revised that function to accommodate NN6.1/NN6.2Win and hopefully
it will accommodate the innerHTML mac browsers (iCab and IE). If anyone
could test it on a non-windows browser I would be grateful.

Have you posted a test page? I'll click some buttons for you and send
you the results.

Peter
Added was
the innerHTML testing so that browsers that execute innerHTML scripts
wouldn't execute them twice.

var innerHTMLFailed=true;
window.onload = checkIt;

function checkIt(){
document.getElementById('myDiv').innerHTML = '<script
type="text/javascript">var innerHTMLFailed = false;<\/script>'}

function loadHTMLFragment(elemId, HTMLFragment)
{
if (document &&
document.getElementById &&
document.getElementById(elemId) &&
document.createElement &&
document.appendChild &&
document.getElementsByTagName &&
{
var el = document.getElementById(elemId);
el.innerHTML = "&nbsp;" + HTMLFragment;
//The &nbsp; is a hack to cause IE to process the
//script elements if the first node in the
//HTMLFragment is a script element.
if(innerHTMLFailed)
{
var d =el.getElementsByTagName('script');
var t = d.length;
for (var x=0;x<t;x++)
{
var newScript = document.createElement('script');
newScript.type = "text/javascript";
newScript.text = d[x].text;
el.appendChild(newScript);
}
for (var y=0;y<t;y++)
{
el.removeChild(el.getElementsByTagName("script")[y]);
}
}

}
}

Next step is a test of the .text attribute since I know of browsers that
do not support setting the .text property of a newScript element.
 
P

Peter Michaux

Hi,

After all this fuss about script insertion and getting scripts to
execute in global scope, I found myself looking through the jQuery
code.

------------------------

// Evalulates a script in a global context
// Evaluates Async. in Safari 2 :-(
globalEval: function( data ) {
data = jQuery.trim( data );
if ( data ) {
if ( window.execScript )
window.execScript( data );
else if ( jQuery.browser.safari )
// safari doesn't provide a synchronous global eval
window.setTimeout( data, 0 );
else
eval.call( window, data );
}
},

------------------------

That window.setTimeout(data, 0) call seems like an easy solution to
the scope problem. I may have missed it but was this every suggested
here instead of all this script element insertion?

Peter
 
P

Peter Michaux

Peter Michaux said the following on 8/22/2007 5:13 PM:



Let me guess, silently, on what that line above does :)


I haven't personally seen that suggestion

I hadn't seen it either but I think it is simple and clever.
and I am not sure what
setTimeout(data, 0) would have to do with any non-Safari browser. And, I
just plain *HATE* eval. Call me bonkers, I just prefer not to use it if
there is a non-eval alternative.

The big issue with eval is that it is slow and the code can't be
optimized. Each time eval is used the string has to be parsed first by
the JavaScript engine etc. However when you are inserting a script
element into a page you are just inducing eval without calling it. It
is eval in disguise with a global scope. And it also has many cross
browser issues that we have been exploring at length for months with
no real solution. The jQuery solution is extremely robust and compact.
It looks like a winner in this global-scoped eval issue. If you keep
fighting with that script insertion, and the jQuery technique doesn't
have any associated problems, then I'm going to call you bonkers on
this one. It's what you've been looking for, isn't it?
And, what does jQuery.trim do? I can pretty well guess what
jQuery.browser does.

I don't know jQuery much.

Peter
 
J

Jon Maz

Hi All,

<quote>
Agreed, use an iframe and save yourself from a "world of pain."
</quote>

You are of course quite right that this is the technically easiest solution.

However a reason for not using an <iframe> just occurred to me - advert
tracking. A key feature of an ad reporting system is to tell you what ads
are shown/clicked on under what urls, and if every ad is in fact being
served via an iframe from the same adServer.php url, then your ad reports
carry at lot less value - possibly to the point of ruining your business, if
it depends on ad revenue.

Now I think about it this might well be the reason most big sites do *not*
load their ads via <iframes>.

:-(

JON
 
R

Richard Cornford

Peter said:
After all this fuss about script insertion and getting scripts to
execute in global scope, I found myself looking through the jQuery
code.

------------------------

// Evalulates a script in a global context
// Evaluates Async. in Safari 2 :-(
globalEval: function( data ) {
data = jQuery.trim( data );

If this trim is removing leading and trailing white space characters (as
may be expected from a method named 'trim') what is the point of doing
that at all? Leading and trailing white space characters are not
significant in javascript source code.
if ( data ) {
if ( window.execScript )
window.execScript( data );
else if ( jQuery.browser.safari )
// safari doesn't provide a synchronous global eval
window.setTimeout( data, 0 );
else
eval.call( window, data );

We have already seen the setting the - this - value is not sufficient
for this issue, and that is what the - call - method does. In this case
the code appears to be trying to use the deprecated feature of
JavaScript(tm) where each object has an - eval - method, though even
executing - eval - as a method of an object may be expected to do no
more than influence the value of - this -.

In any case, ECMA 262 clearly says that this formulation of - eval -
call is allowed to throw an exception, so it has no business appearing
in code that is even attempting to be cross-browser.

Here we also see evidence of the work of a quite inexperienced
javascript author. The style of authoring were an individual is
expecting to add a branch to their code for each new browser they
attempt to accommodate. And an author who has boxed themselves into that
mindset is then incapable of seeing that is - setTimeout - is ever going
to work it is going to work for anything that is coved by either of the
other branches, and so no branching is needed at all, there is no need
to be interested in the type or version of the browser (only whether or
not it has a - setTimeout - function), and the resulting simpler code
will be more consistent, reliable and maintainable. It is a pity that
people insist on inflicting things like JQuery on the world before they
have themselves progressed beyond the novice stage in their javascript
understanding.

The easiest solution is not to design a system where the problem exists.
I may have missed it but was this every suggested
here instead of all this script element insertion?

It has been suggested several times, a very long time ago and only out
of an academic desire for completeness of explanation. Ultimately the
issue does not exist. It is trivial for server-client interactions to
facilitate the server issuing instructions (with or without parameters)
for the client to act, and it is trivial for side effects of those
actions to be the creation of properties of arbitrary objects on the
client, and even for those objects to be executable. But when the
designer insists that the medium of communication should be truly
arbitrary javascript source code then it is that design decision that
introduces any implied necessity to evaluate code in the global
execution context. Make a better design decision and the issue is
irrelevant.

Richard.
 
A

andrea.giammarchi

One thing I
did notice in the code on that page that I didn't care for was appending
script elements to the HEAD section. I prefer to use a scriptDiv(DIV
Element) so that I can completely wipe out any and all scripts at
anytime that I want to :)

Please Randy, if You have few minutes read "dephtly" because script
tag is appended and instantly removed, so You can just add all scripts
at anytime You want because global scope doesn't require "a place to
be runned" (a nested div or outer <html /> is not important, just
execution order is important, as unmodified DOM before and after
execution should be important too) :)

However, I generally agree with You but if You read better that post
and last I've just wrote, I'm quite sure You'll agree with me and
You'll like my proposal, that's syncronous and "strongly" compatible
(probably only old IE4 / NS4 are not compatible -
document.createElement).

Regards,
Andrea Giammarchi
 
A

andrea.giammarchi

If you append to the head element(or any other element) and then
instantly remove that script then it is eligible for garbage collection
and thus makes it a bad idea.
JavaScript is injected inside browser parser (engine), DOM is another
thing ... please show me only one example where a removed script
causes what You're talking about.

Especially if that script block has a
function in it that you want to use later. It may still be there and it
may not. That is why I started using the div element approach.
This approach is obtrusive for every other script and for DOM too.

Another problem with the code is in the evalScript function where it
uses .text to set the text property of a script element. In a Windows
based environment, that is almost foolproof.
what's foolproof? text, using a script element, works perfectly with
IE5, IE 5.5, IE 6 and IE7
Maybe You're thinking about createElement("style") and text IE
problems?


Run it in a Mac browser and
your success ratio (across browsers) will drop to around 50% or so as
there are at least 7 (probably more) that don't support setting the
.text property on a script element and 6 (that I know of) that do
support setting it. I say 50% simply because I am pretty sure the
statistics there are skewed as I don't have a mac to investigate with.
I have not a Mac too, just Safari for windows but I've a friend with
Safari 2 and Mac, I'll ask him if my proposal will cause some problem.
Until this, please tell me exactly what browser for what OSX causes
problems, specifing platform and browser version, thank You.


The only browser, that I know of, that doesn't support createElement on
a SCRIPT element is IE and that is what has led to a lot of this coding
is an effort to cope with IE not implementing createElement on a script
element. If it did, you would code it like this:

var newScript = document.createElement('script');
newScript.type = "text/javascript";
newScriptText = "alert('createTextNode worked')";
var s = document.createTextNode(newScriptText);
newScript.appendChild(s);
It's a simple proposal enanchment, however I tested my proposal with
every used IE (5,5.5,6,7) and it seems to work perfectly. Maybe You're
talking about Mac IE 5.X .... this death browser?


And then you appendChild newScript to a container (whether it be HEAD,
BODY or another container element). Then you merely have to figure out
how to cope with IE. ....


I am not sure it is as "strongly compatible" as you suggest
the failure of setting the .text property in many mac browsers.
please, just test them ... I usually develop for these browsers:
IE6, IE7, FF1.5, FF2, FF3, Safari2, Safari3, Opera8, Opera9

in this case this solution works with IE5 and 5.5 too ... so, these
are 99.9% of used browsers.

Do You write code for IE4 too? In this case, good luck for your
solution!!!


As for your second blog entry, I disagree with these two statements:

I can always say "eval is evil" in that regards because there *IS* an
alternative/different approach to it and eval introduces problems that
dynamic script insertion doesn't introduce. Predominantly it is a scope
issue.
So do You prefere low speed and error prone code (pure JS) parsing
instead of core evaluation after a stable RegExp?
So don't You think that a script tag inside a layout is just a sort of
evaluation?
I'm a bit confused about your position when You talk about
*JavaScript* ...


Second, I don't believe that code evaluation is "always" a bad practice.
I said it's always a BAD practice, in rare case, it's a must.
I suppose the only one obsessed by evaluation are people who don't
think about language nature itsself, *SCRIPTING* ... so use eval if
it's strongly necessary or spend much time to find slower alternatives
(so abort D. Crockford toJSONString method and future FF
implementation too, isn't right?)


That said, the major difference in most of my code and research and what
you posted is that I am looking and working on a basic framework
approach to answer a very generic question and your post is in regards
to a very specific question.

Generic question:

"I retrieved a document using AJAX, insert it in the page and my scripts
don't get executed. How do I cause those script blocks to get executed?"
Answer is on my blog, evalScript does it simply and quickly, 5 lines
of JS code, aren't enough?


And with that question, the answer has to encompass script text, script
source, scope issues, document.write issues, along with some other issues.
Is your research based on document.write method? ... how many days did
You spend to perform this research?


I think that's not so difficult to read a solution and use them, You
spoke about IE problems while IE is perfectly compatible and You
talked about document.write that's never a good practice on DOM
loaded.

I wonder, at this point, if You like jQuery solution that's totally
wrong, asyncronous with safari and not useful to solve the problem
with a call and window as first argument, while You (seems to) hate my
solution that's compatible with safari too and works pretty right with
100% of (mine) tested browsers.

Regards,
Andrea Giammarchi
 
A

andrea.giammarchi

How do you debug code that doesn't exist anymore? There are more reasons
to leave it than there are to remove it. It is a choice. I choose to
leave mine.
my debugger works fine and DOM is not persintently incremented


Say again? How is me putting script blocks inside a sole div element
obtrusive for every other script?
just think about document.getElementsByTagName("script") ... and just
think about DOM incrementation


The only possible problem that could
*ever* be caused by it is if a div element happened to be duplicated in
which case the script (mine) could be modified to create it's own div
element to use.

there are more problems than one ... but leave your personal DIV there
if You feel lucky.
Use this practice at your own risk if You use third party libraries.

What is foolproof on a PC is to set the .text property of a script
element. Trying to do that on other OS'es is a recipe for disaster.
disaster ... LOL!!!

But it does *not* work in 7 mac browsers (and that is only the ones I
know about).
as I've said, I don't have Mac and I don't care, usually, on browser
used by 0.01% of net surfers.

However, thank You for your link, it seems that my basic proposal,
that I've never called perfect but I called them *proposal*, need just
a simple try catch or to be wrote differenlty for iCab and others
using TextNode, really simple, isn't it?

Well done, I'll update my code ... so, at this point, totally amount
of 2 hours against 7 years? :p

What a nice place this is!!! :D

Best Regards,
Andrea Giammarchi
 
A

andrea.giammarchi

Ok Randy, You have a credit inside my code update.

Last line, that doesn't require above clear function and it should be
cross-browser enough to forget this problem, could You confirm it?
http://www.devpro.it/code/163.html

Sorry for my self-packing obsession, however if someone is interested
about source, just indent (beautyfing) them, it should be quite clear
to read / understand :)
 
P

Peter Michaux

Ok Randy, You have a credit inside my code update.

I'm curious if he wants credit in your code.

Last line, that doesn't require above clear function and it should be
cross-browser enough to forget this problem, could You confirm it?http://www.devpro.it/code/163.html

"cross-browser enough"?

Script insertion is only multi-browser.

eval() and setTimeout() solutions work way back to ancient browsers
and perhaps could be candidates for the label "cross-browser".

Sorry for my self-packing obsession, however if someone is interested
about source, just indent (beautyfing) them, it should be quite clear
to read / understand :)

Code below.

In addition to the brittle dependence on navigator.userAgent, I see at
least two superficial bugs.

Peter


| (evalScript = function(e) {
| var h = evalScript.node,
| s = document.createElement("script");
| s.type = "text/javascript";
| s.text = e;
| h.appendChild(s);
| h.removeChild(s);
| }).node = document.getElementsByTagName("head")[0] ||
| document.getElementsByTagName("*")[0];
|
|
| // self packed, (more) cross browser/platform alternative
| // Special thanks to Randy Webb [comp.lang.javascript]
| (function() {
| var head = document.getElementsByTagName("head")[0] ||
| document.getElementsByTagName("*")[0];
| evalScript = /webkit|khtml|shiira|sunrise/
i.test(navigator.userAgent) ?
| function(E) {
| var s = document.createElement('script');
| s.type = "text/javascript";
| s.appendChild(document.createTextNode(E));
| head.appendChild(s);
| head.removeChild(s);
| }
| : ! /icab|ie 5\.2/i.test(navigator.userAgent) ?
| function(E) {
| var s = document.createElement('script');
| s.type = 'text/javascript';
| s.text = E;
| head.appendChild(s);
| head.removeChild(s)
| }
| : function(E) {
| var div = document.createElement("div"),
| style = div.style;
| style.position = "absolute";
| style.border = style.height = style.left =
| style.top = style.width = "0px";
| head.appendChild(div);
| evalScript = function(e) {
| div.innerHTML =
| '<script type"text/javascript">'+
| E + '</script>';
| divr.emoveChild(div.firstChild)
| };
| evalScript(E)
| }
| })();
 
P

Peter Michaux

as I've said, I don't have Mac and I don't care,

That is an unexpected attitude for a professional.

usually, on browser used by 0.01% of net surfers.

This is definitely way off.

However, thank You for your link, it seems that my basic proposal,
that I've never called perfect but I called them *proposal*, need just
a simple try catch or to be wrote differenlty for iCab and others
using TextNode, really simple, isn't it?

Well done, I'll update my code ... so, at this point, totally amount
of 2 hours against 7 years? :p

But where did your two hours get you?


Peter
 
A

andrea.giammarchi

I'm curious if he wants credit in your code.
Since He spent much more time than me to try to solve this problem, I
add his credits in my code.

If He doesn't want its credits, I'll remove instantly ... He should
just tell me ... I don't need his name in my little, personal,
site ... so I can't see where the problem is and credits was add just
for that "big" browser list and their behaviour :)

"cross-browser enough"?

Script insertion is only multi-browser.
probably my bad english doesn't allow me to explain perfectly my
ideas ... thank You for this point

In addition to the brittle dependence on navigator.userAgent, I see at
least two superficial bugs.
I found one, bad replacement (function(e) instead of E) ... now,
please tell me where's the other.

P.S. brittle dependence, rotlf, sounds like Randy "disaster with
text" ... I write code for Web surfers, do You write code for
crackers?

That is an unexpected attitude for a professional.
come on guys, I wrote JSL many times ago ... so please don't teach me
how much could be cross-browser a script.

I'm simply realistic, in real life/job/world, 0.01% of bad browser
choice can't be my problem.

If I'm not wrong, Java 1.6 doesn't compile some code for 1.5 or
1.4 ... isn't right?

So, now look at every famous library over the net and test them with
Randy browser list ... it's quite obvious that a developer can't write
code for people who don't care about Web navigation, standardization
and/or features.

In other case, please ignore try catch and Exceptions in every script,
I use IE4 and I don't need your professional code (lol again, IT
runs!)


This is definitely way off. ....



But where did your two hours get you?
two hours to: write code, do few tests with "every day" browsers,
write post on personal blog, read here (thanks You Peter) ... and
finally, create self-packed cross-browser version.

Can You do better? I hope so ;)

Regards,
Andrea Giammarchi
 
A

andrea.giammarchi

I have already responded to that in two other replies, but please remove
my name from that, ummm, "code".
done, however, thank You for that table

You don't write code for "web surfers", you write code for "web surfers
that use a UA that fits into my little world of browser scripting ability".

Hey Randy, I do my work as you do your one.
At the same time, I don't think I code better than You ... and I don't
think You code better than me too.

You can write code for Commodore-64 too if You like this way and You
think this is a good way to create big size "revolutionary" scripts
using double time to do them.

Why? You could learn a lot based on what you have written so far.
And You could learn a lot on what I written too ;-)

I am curious where you got that 0.01%. Did it come off the top of your
head or out of your posterior as it would be about as reliable from one
place as the other. http://www.w3schools.com/browsers/browsers_stats.asp
http://www.upsdell.com/BrowserNews/stat.htm


I already have, and will continue to make it even better. That can't be
said for your code at the present time because you have already decided
that it is as good as it needs to be (even though it isn't even close).
I've decieded anything about my code ... it is a proposal, just
modified, and last modified version works with probably every row
present in your table (but if a browser is buggy, it can't be my
problem)

My script code is no more obtrusive than any other script block. Do you
remove the script element that you use to contain your script block
also? And, if you know that the script element is there (because you put
it there) then you know you have to deal with it.
of course ... but don't You never think about other developers that
uses third libraries?
I code like You, everything is "mine" and everything is under my
control ... but if I publish something publicly it should care about
every other library (do You know Open Ajax and similar projects?).

So, do You code only for yourself? I think this is not an error, but
this is not a good practice too, expecially if You public your code
over the net.

I don't. Most are written by the kind of people that believe that your
script is a solution to the problem at hand.
because it's a solution for 98% (ok, ok ... 99.9 is too much ...) of
*USED* browsers ... I usually prefere small "quite totally cross
browser" scripts instead of "totally cross browser" big size scripts.

Of course, it's my choice for this crazy Web world, so it's not the
best way to code, just a personal choice.

You mean that garbage, err code, that relies on navigator.userAgent that
sends Safari3 on Windows down the wrong path?
Uh? last script (and probably first one too) works with Safari 2 too,
should I care about Safari 1 and 0.1 beta too?
I remember a WebKit 0.1 alpha, should I test them too?

And I have code that is 99% fail proof, you have code that is 50% fail
proof.
50% of browsers ... but 98% of surfers ;)

If you want to know if something works or not, you could test it
yourself.
That's what I do everytime :)

Since you don't care about any non-PC browser what does it
matter?
This is your opinion, not my way to code :) (and I've recently bought
a Nintento Wii too to code for dedicated Opera version ... do You test
your code for new browsers too or only for "not-so-used" one?)

Besides, it would be trivial to answer you if you would make all
the code for it easily available rather than having to wade through 4 or
5 pages to find it. No thanks.
eh eh ... ok Randy, You are the one!

I didn't know this "place" and probably, if You're one "boss" here,
I'll never come back again.

Good luck with your unique and perfect way to code and find solutions
(really, "only" 7 years for this simple problem? ...)

I went here to talk about my proposal and possible problems but You
talk only about your way to "perfectly" code and your friends agree
with your ego.

So, finally, I respect You because your work is good enough for your
purpose/goals but my work (I write JavaScript from about 10 years) is
good enough for my goals, so We'll probably talk about JS one day but
I'm sure, not "tomorrow" if this is your way to talk about them.

As I said, really sorry (to everyone) for my bad and not so clear
English knowledge and best regards to everyone,
Andrea Giammarchi
 
A

andrea.giammarchi

You detect only IE, in your piece of code, and there's any solution
for innerHTML compatible browsers (while my last piece of ... uhm ...
"code", has it)

At this point, this is a quite steril flame and I don't want to go on
with them.

Best regards,
Andrea Giammarchi
 
R

Richard Cornford

Randy said:
Richard Cornford said the following on 8/26/2007 12:10 PM:

How is using .call trying to depend on executing eval as a
method of an object?

Isn't that precisely what the call and apply methods do?
Other than that, I don't see anything that even comes close
to what you are describing (I am more curious than anything).

Consider that - window.eval( ... ) - is calling - eval - as a method of
an object, but ECMAScript rules say that - window.eval - will result in
a Reference type with a null 'base' property (because window is a
Variable object (at least the global object is a variable object for the
global execution context) ). In practice that should make no real
difference as then the - this - value would default to the global/window
object anyway. However, in this context it must make some sort of
difference else the line of code would be obviously ineffective and
would not be being used (it is the branch that Mozilla/Gecko browsers
will (mostly) be taking so if it were ineffective that fact should have
been exposed by testing).

While that is always the "easiest" solution, it is not
always the most feasible solution. I have always said that
an "AJAX type" site should have the backend designed to be
handled by AJAX on the client side. The fact remains though
that not all sites are easily reconfigured to be an AJAX
Site without a complete re-write of the entire site.

Which would suggest that changing the delivery technology is not an
action that should be driven by the whims of fashion.
If your boss comes to you and says "I want our HTML4.01
Strict script infested site turned into an AJAX site by
next Friday", you have two choices:

1) Find another job.
2) Kill yourself to please the person signing the check.

There (probably) will be people for whom those are the only choices (as
there (probably) are (very poor) bosses who will not entertain reasoned
or technical arguments in the assessment of decision making).
Personally, that is a very long way form an exclusive list of my
options. And while my boss does consider it his job to come up with
constant stream of 'new' ideas (usually 3 or 4 a week) he does
understand enough about the business to take those ideas to the various
technical experts he employs, discuss their feasibility and accept that
some of them will non-starters.
Very very few people will take Option 1 in the Real World.
It is trivially simple to take Option 1 in a Theoretical
World.

In the end though, aren't you just saying that given a particular
starting point (that is not an inevitable starting point) and totally
constrained in the direction that is to be taken from that point
(without regard for any technical considerations) the outcome might be
somewhat less than what could be considered desirable? Which is true,
but can hardly be expected to influence or constrain a consideration of
what may be regarded 'good' design/implementation criteria.

Richard.
 
R

Richard Cornford

Randy said:
Richard Cornford said the following on 9/1/2007 2:49 PM:

Are you saying that "AJAX" is a whim of fashion?

No, I am saying that a desire to reconfigure an existing site as an AJAX
site might be a whim of fashion, and if it were that may not be a good
enough justification for doing so.

That is probably 95% of the managers in charge of the web area
of the IT Department.
<snip>

I hope things are not really that bad. I can understand that things may
be widely done as badly as they are as a result of pandemic ignorance of
the technologies, but it would be depressing to attribute it to a
widespread unwillingness to listen to reasoned argument.

Richard.
 
P

Peter Michaux

Are you saying that "AJAX" is a whim of fashion? I think it is something
that has been going on for a long time and happen to get a buzzword name
for it that people like to throw around at country club meetings "Yeah,
we have an AJAX site". To which I usually reply "Sorry you have such an
undependable system in place".

It can't be all that undependable giving how wide spread it is. If it
only worked 10% of the time then few people would use it.

As long as there is a declared restricted set of browsers being
supported or a degradation path then the page/site can be dependable.

Peter
 
T

Thomas 'PointedEars' Lahn

Peter said:
It can't be all that undependable giving how wide spread it is. If it
only worked 10% of the time then few people would use it.

So all of us should eat sh*t; billions of flies cannot be wrong.

I am not arguing that XHR is a Bad Thing generally; as long as a fallback
is provided, then there is nothing wrong with it and it might do some good.
But your argument is obviously flawed.

With incompetent authors it is like this: no complaints, no changes.


PointedEars
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,142
Latest member
arinsharma
Top