I have a question on Javascript and DOM; shouldn't the following code retrieve the three foo:bar elements in the body? The alert window displays zero. It doesn't work in any browser I have (not even Chrome Canary). Thank you for helping, have a nice weekend.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:foo="http://example.com">
<head>
<title>Hello!</title>
<script type="text/javascript">
function bodyLoad() {
var extElements = document.getElementsByTagNameNS('http://example.com', 'bar');
alert(extElements.length);
}
</script>
</head>
<body onload="bodyLoad();">
<foo:bar>First Foo-Bar</foo:bar>
<foo:bar>Second Foo-Bar</foo:bar>
<foo:bar>Third Foo-Bar</foo:bar>
</body>
</html>
You are likely serving the document with the wrong content type. The browser has to treat it as XML for namespaces to be recognized, so you need to use application/xhtml+xml or another XML content-type, and not text/html.
As an aside, your Doctype is wrong. If you want to use a DTD, then you will need one that includes the elements you are using from the foo namespace. If you don't, then just get rid of the Doctype — it has no bearing on rendering mode in XML documents (again, text/html documents are treated as tag soup, not XML).
Related
I have recently read the following article about a DOM-based XSS:
https://www.netsparker.com/blog/web-security/dom-based-cross-site-scripting-vulnerability/
But the examples provided in the article are not working as described. I created the HTML example file:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head></head>
<body>
<script>
document.write("<b>Current URL</b> : " + document.baseURI);
</script>
<h1> Welcome on my Example Page </h1>
</body>
</html>
I have put the above file in an application folder of a Web-Application deployed on the JBoss server and I have called the resource from my browser ( I have tried both IE 11 and Firefox). IE 11 shows the resulting HTML content like this:
Current URL : undefined
Welcome on my Example Page
while Firefox shows the resulting HTML content like this:
Current URL : https://localhost:8443/ukvlei/example.html
Welcome on my Example Page
In both cases, I can not force any of the browsers to execute the java script function after the # sign, as described in the article. When I type
https://localhost:8443/ukvlei/example.html#<script>alert(1)</script>
in the address bar of the browser, I get the following HTML content:
under IE 11:
Current URL : undefined
Welcome on my Example Page
under Firefox:
Current URL : https://localhost:8443/ukvlei/example.html#%3Cscript%3Ealert(1)%3C/script%3E
Welcome on my Example Page
What am I doing wrong, so that I cannot execute the java script in any of the browsers?
Thank you!
You haven't run the URI through decodeURIComponent so that the URI syntax is converted back to text.
I want to thank both #scagood and #Quentin, with whose help I got my question answered. So, the answer is:
1.) Apperantly the provided example in the article is out of date, as it is around three years old, so:
2.) Use window.location.href instead of document.baseURI;
3.) To make the example run both under IE and Firefox, decode the URL using decodeURIComponent.
So, the working example HTML file now looks like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head></head>
<body>
<script>
document.write("<b>Current URL</b> : " + decodeURIComponent(window.location.href));
</script>
<h1> Welcome on my Example Page </h1>
</body>
</html>
I'm trying to get information out of a JSON and I get an error that my XML is not well formed. It points to
if((jsonResponse[0].error) && (jsonResponse[0].error.type == 101)) {
----------------------------^
Here's the context:
<?xml version="1.0" encoding="UTF-8" ?>
<!--As DOCTYPE either the strict XHTML declaration or
"-//HbbTV//1.1.1//EN" "http://www.hbbtv.org/dtd/HbbTV-1.1.1.dtd"
shall be used as described in the HbbTV-standard: A.2.6.2.-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--Required XML-namespace as described in the HbbTV-standard: A.2.6.2.-->
<html xmlns="http://www.w3.org/1999/xhtml">
Wrap your JavaScript in CDATA section so that && isn't interpretted as markup:
<script>
<![CDATA[
JaveScript code here
]]>
</script>
Much better solution is move out your script code into separated file and use src attribute to define path, you won't need work with cdata anymore.
The "span" tag is invalid, how do I make it valid?
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
...
<script type="text/javascript">
var locations = [
[
'Kirklevington Village Hall',
'<span style="font-size:2;"><b>Kirklevington Village Hall</b>,<br />Forest Lane,<br />Kirklevington,<br />Stockton on tees,<br />TS15 9LX</span>',
54.4825,
-1.33663
]
];
</script>
Enclose your script in <![CDATA[ and ]]> to make it appear as a comment to the validator.
More info here
The simplest way is to put the script code to a separate file, say foo.js, and refer to it using <script "src=foo.js" type="text/javascript"></script>. Other methods involve various techniques for “escaping” the content of the script element, and they are clumsy and error-prone.
The XHTML 1.0 spec, appendix C, recommends: “Use external scripts if your script uses < or & or ]]> or --.”
I'm having some problems with getting one of my site pages with IE8. It works fine in IE9, Safari (both PC & Mac) & Firefox (Mac). I'm using a find(tag1).html(tag1) call sequence to do a title substitution, but I get the following error in IE8 when I debug it in the IE script debugger, and this in the html(tag2) function:
Unexpected call to method or property access
The find(tag1) function seems to return the enclosing object (i.e. #sidebar), rather than the nested object #sidebarheader, and this causes problems when later making the html(tag2) call.
I've created a representative test case as follows:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>JQuery .find() test case</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.4.js"></script>
<script type="text/javascript">
function UpdateHeader() {
$('#sidebar').find('header').html("New Title"); // IE8, nesting div's in the find fct. will not discover the child div
}
document.ready = UpdateHeader;
</script>
</head>
<body>
<div style="height: 400px; width: 390px">
<div id="jqm-home">
<div id="page">
<div id="sidebar">
<div id="sidebarheader">
<header>Old Title</header>
</div>
</div>
</div>
<p onclick="UpdateHeader();">Click to update title</p>
</div>
</div>
</body>
</html>
And here is the jsFiddle test case:
http://jsfiddle.net/bnmcK/21/
Has anybody a suggestion on how to get this to work in IE8?
In order to support the new HTML 5 elements in older versions of IE (8 and below), there's a handy trick, which involves creating a dummy element before running your script.
So, simply calling document.createElement('header'); in your page will solve the problem, see here.
For the full explanation, this post does a nice job of providing an explanation.
Also, html5shiv is a project that solves this problem for other elements too.
<header> is a HTML5 tag, which IE8 doesn't know about (IE9 however, supports this tag). Since you're declaring XHTML 1.0 transitional, I'd suggest using a <h1> tag instead, which will work just fine in IE8.
I'm attempting to create an <iframe> using JavaScript, then append a <script> element to that <iframe>, which I want to run in the context of the <iframe>d document.
Unfortunately, it seems I'm doing something wrong - my JavaScript appears to execute successfully, but the context of the <script> is the parent page, not the <iframe>d document. I also get a 301 Error in Firebug's "Net" tab when the browser requests iframe_test.js, though it then requests it again (not sure why?) successfully.
This is the code I'm using (live demo at http://onespot.wsj.com/static/iframe_test.html):
iframe_test.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title><iframe> test</title>
</head>
<body>
<div id="bucket"></div>
<script type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#bucket').append('<iframe id="test"></iframe>');
setTimeout(function() {
var iframe_body = $('#test').contents().find('body');
iframe_body.append('<scr' + 'ipt type="text/javascript" src="http://onespot.wsj.com/static/iframe_test.js"></scr' + 'ipt>');
}, 100);
});
</script>
</body>
</html>
iframe_test.js
$(function() {
var test = '<p>Shouldn\'t this be inside the <iframe>?</p>';
$('body').append(test);
});
One thing that seems unusual is that the the code in iframe_test.js even works; I haven't loaded jQuery in the <iframe> itself, only in the parent document. That seems like a clue to me, but I can't figure out what it means.
Any ideas, suggestions, etc. would be much appreciated!
Had the same problem, took me hours to find the solution.
You just need to create the script's object using the iframe's document.
var myIframe = document.getElementById("myIframeId");
var script = myIframe.contentWindow.document.createElement("script");
script.type = "text/javascript";
script.src = src;
myIframe.contentWindow.document.body.appendChild(script);
Works like a charm!
I didn't find an answer to my original question, but I did find another approach that works even better (at least for my purposes).
This doesn't use jQuery on the parent page (which is actually a good thing, as I'd prefer not to load it there), but it does load jQuery in the <iframe> in an apparently completely valid and usable way. All I'm doing is writing over the <iframe>'s document object with a new one created from scratch. This allows me to simply include a <script> element in a string which I then write to the <iframe>'s document object.
The code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>frame</title>
</head>
<body>
<div id="test"></div>
<script type="text/javascript">
// create a new <iframe> element
var iframe = document.createElement('iframe');
// append the new element to the <div id="bucket"></div>
var bucket = document.getElementById('test');
bucket.appendChild(iframe);
// create a string to use as a new document object
var val = '<scr' + 'ipt type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js"></scr' + 'ipt>';
val += '<scr' + 'ipt type="text/javascript"> $(function() { $("body").append("<h1>It works!</h1>"); }); </scr' + 'ipt>';
// get a handle on the <iframe>d document (in a cross-browser way)
var doc = iframe.contentWindow || iframe.contentDocument;
if (doc.document) {
doc = doc.document;
}
// open, write content to, and close the document
doc.open();
doc.write(val);
doc.close();
</script>
</body>
</html>
I hope this helps someone down the road!
The answer to the original question is simple - the execution of the script is done by jquery, and since jquery is loaded in the top frame, this is where the script runs too, no matter where you are appending it. A smarter implementation of jquery can no doubt be made to use the correct window object, but for now things are how they are.
As to the workarounds, you already have two good answers (even if one is your own). What I might add is that you can use one of those workarounds to include jquery.js in the iframe, and then get that jquery object instead of the top one to insert your additional markup... but that may very well be overkill too.