The CSS Rule object - javascript

According this site externalcss3 The CSS Rule object of the styleSheet object lets you access the individual rules of a stylesheet.
So If I try to run this piece of code(*) on stackoverflow page, using the javascript console, I expect to see some CSS Rules written in this page http://cdn.sstatic.net/stackoverflow/all.css?v=04e0337352b3.
(*)
var mysheet=document.styleSheets[0]
var myrules=mysheet.cssRules? mysheet.cssRules: mysheet.rules
for (i=0; i<myrules.length; i++) {
console.log(myrules[i].selectorText.toLowerCase());
}
Actually the result of console.log is something different from what I would expect:
object[type="application/x-shockwave-flash"], object[type="application/futuresplash"], object[data*=".swf"], object[src*=".swf"], embed[type="application/x-shockwave-flash"], embed[type="application/futuresplash"], embed[src*=".swf"]
What have I Missed? Sorry for my ignorance and your time.

It seems you can only access the rules in the CSS file if they are from the same domain.
Read this thread: Reading the rules of a cross domain CSS file in DOM

Related

Adding StyleSheets to Firefox Bootstrapped Addon

Accordion to Using the Stylesheet Service
Above mentioned document also states:
loadAndRegisterSheet fails if CSS contains #id. '#' must be percent-encoded, details see bug 659650.
The bag report was made on 2011-05-25. Is it still a bug or has it been resolved?
There is another way of adding CSS but that is per window and I prefer to get this one sorted.
Update:
Here is the content of the style-sheet
#rpnethelper-separator2:last-child { display: none; }
#rpnethelper-menuitem {
list-style-image: url('icon16.png');
}
This is the actual code (plus added console calls)
register: function(css) {
let sss = Components.classes['#mozilla.org/content/style-sheet-service;1']
.getService(Components.interfaces.nsIStyleSheetService);
let cssURI = Services.io.newURI(css, null, null);
sss.loadAndRegisterSheet(cssURI, sss.USER_SHEET);
},
I tried it with try{} catch{} and I dont get any errors.
How/where can USER_SHEET be viewed?
For now, I am going to use an inline style (which doesn't support the pseudo classes) but I would still like to resolve this issue.
Final Update:
For some reason, the code that wasn't working with USER_SHEET, works fine with AUTHOR_SHEET
Funny thing is, after all that, I decided it is not worth the extra processing just for one pseudo class, so I opted for the (simple) inline style
You forgot to specify the correct namespace. Add the following as the first line to your sheet.
#namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
The docs you already linked state:
Stylesheets added using this service get applied to both chrome and content documents. Remember to declare the correct namespace if you want to apply stylesheets to XUL documents.
Also, if you're targeting Firefox 18 and later (and really, supporting earlier versions has no merit as those are unsupported and contain known security vulnerabilities, so users shouldn't be using them), you should consider using nsIDOMWindowUtils.loadSheet instead. This will only load the sheet into the actual window, instead of applying it globally to all windows incl. websites.
if (window instanceof Ci.nsIInterfaceRequestor) {
let winUtils = window.getInterface(Ci.nsIDOMWindowUtils);
let uri = Services.io.newURI(..., null, null);
winUtils.loadSheet(uri, Ci.nsIDOMWindowUtils.AUTHOR_SHEET);
// Remove with winUtils.removeSheet() again on shutdown
}
Edit You'll want to use AUTHOR_SHEET most of the time (be it with the style sheet service or window utils). This is more equivalent to xml-stylesheet in overlays.
loadAndRegisterSheet fails if CSS contains #id. '#' must be percent-encoded, details see bug 659650.
The bag report was made on 2011-05-25. Is it still a bug or has it been resolved?
That bug report only applies data: URIs. Also, that bug report is invalid, # has special meaning in URIs and therefore you'll have to encode it when it is part of the URI directly (as is the case with data: URIs). If you're registering a regular chrome:/resource:/file:/http: URI, you don't need special encoding.

GWT HTML-Class Tag Styles not obfuscated

I got a legacy xsl transformation which results in plain HTML and which is bound then to a widget with a GWT HTML field. Its currently looking like this:
HTML html = new HTML
html.setHTML(result)
inside the UiBinder part of the widget there is a
<ui:style>
<!-- old legacy styles -->
</ui:style>
the problem now is, that there are a lot of styles in there and they seem to get obfuscated while the names in plain HTML which is set in the HTML container is not obfuscated - so the result is unstyled.
I tried to set
#external .*;
which is not allowed in there. Prefixing all styles and using #external prefix-* has the same effect:
[ERROR] Line 6: The annotation #CssResource.ClassName is disallowed for this location
[ERROR] Line 7: Syntax error on token "*", delete this token
Is it possible to disable obfuscation for this one UiBidner file or force gwt to also obfuscate the HTML stuff that comes in?
I do not recall if you can use the #external .* syntax into an inline <style> element. Maybe try to explode all styles (or just with a couple of them - with and without the leading dot).
But if all styles are meant just to be legacy, don't bother an simply create a #NotStrict CssResource. Something like:
interface MyBundle extends ClientBundle {
#Source("legacy.css")
#NotStrict
CssResource legacy();
}
And remember to call its ensureInjected().

error with google swiffy calling runtime.js multiple times in the same page

I have converted multiple swf files using google swiffy v5.2 and will have my new animations displayed on many different pages, most of which I do not have control of or access to. In order for the animation to work it needs the swiffy's runtime.js file, which might look something like this on the page:
<script src="https://www.gstatic.com/swiffy/v5.2/runtime.js"></script>
The problem arises when I either have multiple instances of the animation on the same page or a client has this runtime.js file included on their own. When checking the javascript console I get this error:
Uncaught TypeError: Cannot redefine property: __swiffy_override - runtime.js:186
If i was only worried about the conflict with myself I could possibly keep track of a variable or check if the script src existed already, however I do not have this luxury when a client's page may have renamed or changed the source to this file.
Is there a way to prevent the swiffy runtime.js from redefining this property when there are multiple instances of the same javascript file being included on the page?
I imagine you are seeing this problem happen when using AS3 swfs, which have Document classes applied to them. For example, say you have animationAS3.swf, which uses AnimationBaseClass.as. When it is "compiled" by Google Swiffy service the resultant JSON data will contain
{"internedStrings":["...", "AnimationBaseClass", "..."] ....}
The Google Swiffy runtime applies JavaScript's defineProperties() or perhaps defineProperty() to seal an "AnimationBaseClass" object it creates. So, when another instance of the data is loaded the Swiffy runtime attempts to do the same thing again, and the JavaScript interpreter says "Hey, I've already defined that object, I won't redefine it."
The solution I've found, which I believe is inefficient, is to rename the class before giving the data to the Swiffy runtime. Like this:
var classEnumerator = 0;
$.getJSON('animationAS3.json', function(data) {
// Due to "TypeError: Cannot redefine property: AnimationBaseClass",
// we need to enumerate the name of the class. I have no idea about
// the impact on resource usage when doing this.
var classNameIndex;
var i = data.internedStrings.length;
while(i--) {
if (data.internedStrings[i].indexOf("AnimationBaseClass") > -1) {
classNameIndex = i;
}
}
data.internedStrings[classNameIndex] = "AnimationBaseClass_" + (classEnumerator++));
}

Detect if stylesheets fail to load (not working on Firefox)

I have cobbled together a script from different sources, that helps me to put some fallbacks in place when a stylesheet fails to load (specifically for me, Pictos server is not always reliable).
This works great, but fails on Firefox for some reason, it doesn't process anything within the if statement. I've tried running it through JSHint and nothing serious is coming up.
Any ideas?
$(document).ready(function(){
$.each(document.styleSheets, function(i,sheet){
if(sheet.href==='http://get.pictos.cc/fonts/357/9') {
var rules = sheet.rules ? sheet.rules : sheet.cssRules; // Assign the stylesheet rules to a variable for testing
$('body').addClass('pictos-working');
$('.pictos-fallback').hide(); // Hide fallbacks
// If the stylesheet fails to load...
if (rules.length === 0) {
$('.pictos').hide(); // Hide Pictos tags so we don't get random letters
$('body').removeClass('pictos-working'); // Remove 'working' class
$('.pictos-fallback').show(); // Show fallbacks
}
}
});
});​
Your style sheet detection method is not reliable. cssRules is null when the style sheet originates from a different domain, because of the Same origin policy.
Instead of detecting the existence of a css rule through the cssRules object, check if a rule from the style sheet is being applied:
if ($('selector').css('property') === 'expectedvalue') {
// Loaded
} else {
// Not loaded.
}
Just some suggestions for improvement that might help:
why a nested if? since you only have two scenarios, use if then else..
are you sure that cssRules is zero when the file doesn't load? maybe there are some headers or metadata that load.. Where did you find this property?
something I just found: http://www.quirksmode.org/dom/w3c_css.html

When to use document.implementation.createHTMLDocument?

What are some use cases and is it deprecated? As I found out at http://groups.google.com/group/envjs/browse_thread/thread/6c22d0f959666009/c389fc11537f2a97 that it's "non-standard and not supported by any modern browser".
About document.implementation at http://javascript.gakaa.com/document-implementation.aspx:
Returns a reference to the W3C DOMImplementation object, which
represents, to a limited degree, the environment that makes up the
document containerthe browser, for our purposes. Methods of the object
let you see which DOM modules the browser reports supporting. This
object is also a gateway to creating virtual W3C Document and
DocumentType objects outside of the current document tree. Thus, in
Netscape 6 you can use the document.implementation property as a start
to generating a nonrendered document for external XML documents. See
the DOMImplementation object for details about the methods and their
browser support.
Given that it provides methods (such as createHTMLDocument) for creating a non-rendered document outside of the current document tree, would it be safe to feed it untrusted third party HTML input that may contain some XSS? I ask because I would like to use createHTMLDocument for traversal purposes of third party HTML input. May that be one of the use cases?
I always use this because it doesn't make requests to images, execute scripts or affect styling:
function cleanHTML( html ) {
var root = document.implementation.createHTMLDocument().body;
root.innerHTML = html;
//Manipulate the DOM here
$(root).find("script, style, img").remove(); //jQuery is not relevant, I just didn't want to write exhausting boilerplate code just to make a point
return root.innerHTML;
}
cleanHTML( '<div>hello</div><img src="google"><script>alert("hello");</script><style type="text/css">body {display: none !important;}</style>' );
//returns "<div>hello</div>" with the page unaffected
Yes. You can use this to load untrusted third-party content and strip it of dangerous tags and attributes before including it into your own document. There is some great research incorporating this trick, described at http://blog.kotowicz.net/2011/10/sad-state-of-dom-security-or-how-we-all.html.
The technique documented by Esailija above is insufficient, however. You also need to strip out most attributes. An attacker could set an onerror or onmouseover element to malicious JS. The style attribute can be used to include CSS that runs malicious JS. Iframe and other embed tags can also be abused. View source at https://html5sec.org/xssme/xssme2 to see a version of this technique.
Just a cleaner answer besides #Esailija and #Greg answers:
This function will create another document outside the tree of current document, and clean all scripts, styles and images from the new document:
function insertDocument (myHTML) {
var newHTMLDocument = document.implementation.createHTMLDocument().body;
newHTMLDocument.innerHTML = myHTML;
[].forEach.call(newHTMLDocument.querySelectorAll("script, style, img"), function(el) {el.remove(); });
documentsList.push(newHTMLDocument);
return $(newHTMLDocument.innerHTML);
}
This one is fantastic for making ajax requests and scraping the content will be faster :)

Categories

Resources