I'm using the following javascript inside the Chrome extension Web Override to attempt to replace certain text on all Facebook pages, but it is not working.
document.addEventListener('DOMContentLoaded', function() {
document.body.innerHTML = document.body.innerHTML.replace('Friend Name', 'Silly Nickname');
}, false);
setTimeout(function(){
document.body.innerHTML = document.body.innerHTML.replace('Friend Name', 'Silly Nickname');
}, 3000);
If I manually run the replace function in the console after page load it does what I expect. Why isn't it running automatically?
The only console error I'm getting is as follows, but I don't think it's related to this plugin/code because it shouldn't be loading jquery.
Refused to load the script 'https://code.jquery.com/jquery-3.1.1.min.js' because it violates the following Content Security Policy directive
Unfortunately I can't be sure because the source is VM1771:7.
If it is the JQuery thing, is there anything I can do? If not, what is wrong with the code?
String.prototype.replace expects either a string or a regex as the first argument, and in case of a string, it only replaces the first occurrence. That occurrence could be in some metadata, class name, etc.
If you want all occurrences to be replaced, you should use the regex option:
document.body.innerHTML = document.body.innerHTML.replace(/Friend Name/g, 'Silly Nickname');
The g flag here means "global", i.e apply this to all occurrences. You could also use gi for case insensitivity.
I'm able to set line break with javascript in an element, but I can't read them.
Example:
<div id="text"></div>
Js:
document.getElementById("text").innerHTML = "Hello <br /> World";
var x = document.getElementById("text").innerHTML;
if(x == "Hello <br /> World")
{
alert('Match');
}
There is no match in my case...
It is pretty much never a good thing to get the .innerHTML property from an object and then try to compare it to some exact string. This is because the only contract the browser has is to return to you equivalent HTML, not necessarily the exact same HTML. This may not be a problem if there are no nested DOM elements in what you are requesting, but can often be a problem if there are nested HTML elements.
For example, some versions of IE will change the order of attributes, change the quoting, change the spacing, etc...
Instead, you should either search the actual DOM for what you want or look for only a smaller piece of the HTML which you know can't change or use a search algorithm that is tolerate of changes in the HTML.
As Niels mentioned in a comment, Chrome, IE11 and Firefox all return "Hello <br> World" which you can see for yourself with a simple debugging statement like this:
console.log("'" + x + "'");
Working demo to see for yourself what it shows: http://jsfiddle.net/jfriend00/zc59x2bL/
FYI, your code also contains an error. You need to pass document.getElementById() a string which would be document.getElementById("test"), not document.getElementById(test).
this question is difficult to summarize in a question title
UPDATE
I created a JSFiddle that builds an obfuscated string out of your input based on the letters extracted from this question: You can access it here, or would a gist be easier?
I recently came across a fun bit of obfuscated JavaScript in this profile that looks like this:
javascript:[[]+1/!1][1^1][1>>1]+({}+[])[1<<1^11>>1]+([]+!!-
[])[1<<1]+[/~/+{}][+!1][-~1<<1]+([]+/-/[(!!1+[])[1>>1]+(!!1
+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]+([,][
~1]+[])[1-~1]+[[]+{}][!1.1%1][11111.1%11.1*111e11|!1]+(/1/+
1/[1<1][1%1])[1^11]+[[],[]+{}][1][+1]+(/<</[1]+[])[1/1.1&1]
Sorry to ruin the surprise but when this is evaluated it returns this:
"I love you" in Chrome
"I lone you" In Firefox
"I lo[e you" in IE10
The way this works when broken out, is to generate a series of messages and to pull letters out of them like so (using the "I" as an example):
[]+1/!1
returns
"Infinity"
then
[[]+1/!1]
creates this array:
["Infinity"]
then
[[]+1/!1][1^1]
Takes the first (1^1 == 0) element of that array
"Infinity"
finally
[[]+1/!1][1^1][1>>1]
Takes the first (1>>1 == 0) char of that string
"I"
Other strings that are generated include:
({}+[]) -> "[object Object]" (where the space comes from)
([]+!!-[]) -> "false" (used for it's "l")
[/~/+{}][+!1] -> "/~/[object Object]" (this is used for an "o")
(/<</[1]+[]) -> "undefined"
I was interested in finding a replacement for the "n" and "[" and came up with this:
String.fromCharCode(('1'.charCodeAt(0)<<1)+(10<<1))
Which I feel in in the spirit of using 1's and 0's, but violates one of the more elegant aspects of the original code which is the appearance of having nothing to do with strings at all. Does anyone else have an idea of how to generate a "v" that is in keeping with the original obfuscated code?
Here is some extra information that was found after many talented JavaScript programers took a deeper look at this
Firefox returns "I lone you" Because of this line:
([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]+
[1^11<<1] trims a specific character from this:
([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])
Which evaluates to this:
"function test() {
[native code]
}"
Which looks like we might have our "V"!!!
Chrome returns "I love you", because the same code returns this:
"function test() { [native code] }"
Before the question is closed for questionable connection with "a real programming issue", I thought I'd add a summarized solution that builds on #Supr's, #Cory's and #alpha123's, behold:
alert([[]+1/!1][1^1][1>>1]+({}+[])[1<<1^11>>1]+(
[]+!!-[])[1<<1]+[/~/+{}][+!1][-~1<<1]+[([]+/-/[(
!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(
!!1+[])[1^1]])[1+(1^(11+1+1)<<1)],([]+/-/[(!!1+[
])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[
])[1^1]])[1^11<<1],([]+/-/[(!!1+[])[1>>1]+(!!1+[
])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11
+1+1)<<1]][((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<
1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1<<1<<1<<1
)+1<<1]==({}+[])[1^1])*1)+((([]+/-/[(!!1+[])[1>>
1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1
]])[(1^11<<1)-1]==({}+[])[1^1])<<1)]+([,][~1]+[]
)[1-~1]+[[]+{}][!1.1%1][11111.1%11.1*111e11|!1]+
(/1/+1/[1<1][1%1])[1^11]+[[],[]+{}][1][+1]+(/<</
[1]+[])[1/1.1&1])
Given the complexity of the code and the message it produces it's almost like the JavaScript engine is telling how special you make it feel :)
First of all, I would like to thank Jason and all the contributors for playing with that funny snippet. I have written that piece of code just for fun in order to send it to my wife on February 14 :) Having only Chrome installed on the laptop I had no options to check how it works in Firefox and IE. Moreover, I haven't really expected that toString() representation of build-in methods might look differently in other browsers.
Now, moving to the real problem, let's precisely have a look at the code. Yes, "v" was the real "problem" here. I found no other ways of getting this letter except parsing [native code] string, which can be taken from any built-in method. Since I limited myself with having no strings and no numbers except 1 used, I needed to exploit some method that has only available characters in its name.
Available characters can be obtained from existing keywords and string representations, i.e. from the start we had NaN, null, undefined, Infinity, true, false, and "[object Object]". Some of them can be easily converted to strings, e.g. 1/!1+[] gives "Infinity".
I have analyzed different build-in methods for arrays [], objects {}, regular expressions /(?:)/, numbers 1.1, strings "1", and discovered one beautiful method of RegExp object called test(). Its name can be assembled from all available characters, e.g. "t" and "e" from true, and "s" from false. I have created a string "test" and addressed this method using square brackets notation for regex literal /-/, correctly identified in this line:
/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]]
As was already discussed, this piece of code is evaluated in Chrome as:
function test() { [native code] }
in Firefox as:
function test() {
[native code]
}
and in IE as:
function test() { [native code] }
(in the latter pay special attention to the space before function keyword)
So, as you clearly see, my code was getting the 24th character from the presented string, which in Chrome was "v" (as was planned), but unfortunately in Firefox and IE -- "n" and "[" respectively.
In order to make the same output in all the browsers, I have used different approach than illustrated in the other answers. Now the modified version looks like that:
javascript:[[]+1/!1][1^1][1>>1]+({}+[])[1<<1^11>>1]+([]+!!-
[])[1<<1]+[/~/+{}][+!1][-~1<<1]+/\[[^1]+\]/[([]+![])[1<<1<<
1]+(/|/[(1+{})[1+11>>>1]+[[]+{}][+!1][1]+([]+1/[])[1<<1>>1]
+([1<1]+[])[1+11>>>1+1]+[[!!1]+1][+[]][1-1]+([]+!!/!/)[1|1]
+(/1/[1]+[])[!1%1]+(-{}+{})[-1+1e1-1]+(1+[!!1])[1]+([]+1+{}
)[1<<1]+[!!/!!/+[]][+[]][1&1]]+/=/)[1e1+(1<<1|1)+(([]+/-/[(
!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1
]])[1^1]==+!1)]+(!![]+{})[1|1<<1]+[1+{}+1][!1+!1][(11>>1)+1
]](([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+
(!!1+[])[1^1]]))[1&.1][11>>>1]+([,][~1]+[])[1-~1]+[[]+{}][!
1.1%1][11111.1%11.1*111e11|!1]+(/1/+1/[1<1][1%1])[1^11]+[[]
,[]+{}][1<<1>>>1][1||1]+(/[<+>]/[1&1|1]+[1.1])[1/11.1&1.11]
However, in order to intrigue the readers I won't provide a solution for that. I honestly believe that you will easily understand how it works... and some can even surprise their beloved in cross-browser way ;)
P.S. Yet Another Obfuscator
Inspired by Jason's idea to create a universal obfuscating tool, I have written one more. You can find it at JSBin: http://jsbin.com/amecoq/2. It can obfuscate any text that contains numbers [0-9], small latin letters [a-z], and spaces. The string length is limited mostly with your RAM (at least the body of my answer was successfully obfuscated). The output is supported by Chrome, Firefox, and IE.
Hint: the tool uses different obfuscation approach than was presented above.
Why isn't the native code bit from the question being used? This one gives a 'v' in both Chrome and Firefox:
([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]>([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11+1+1)<<1]?([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]:([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11+1+1)<<1]
Edit to support IE and do it without the ternary operator:
This one works in Chrome, IE, and FF. Builds an array and uses == to determine browser.
[([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1+(1^(11+1+1)<<1)],([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1],([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11+1+1)<<1]][((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1<<1<<1<<1)+1<<1]==({}+[])[1^1])*1)+((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1^11<<1)-1]==({}+[])[1^1])<<1)]
Readable:
[
//ie
([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1+(1^(11+1+1)<<1)],
//ch
([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1],
//ff
([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^(11+1+1)<<1]
]
[
//ch?
((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1<<1<<1<<1)+1<<1]==({}+[])[1^1])*1)+
//ff?
((([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1^11<<1)-1]==({}+[])[1^1])<<1)
]
This is about as close as I could get, unfortunately it violates the convention of the original obfuscation by making a call to unescape():
unescape((/%/+[])[1]+(/1/[1]+[])[1%1]+(+!1)+(+!1)+(1e1+(11*(1-~1)<<1)))
Teardown:
(/%/+[])[1] => "%"
(/1/[1]+[])[1%1] => "u"
(+!1) => "0"
(+!1) => "0"
(1e1+(11*(1-~1)<<1)) => "76"
===========================
unescape("%u0076") => "v"
Other ideas:
Somehow get to unescape("\x76")
Somehow convert 118 without calling String.fromCharCode()
Get the text from an exception with the word "Invalid" in it
Updates:
I started playing code golf and have been making it shorter, replacing parts with more 1s, etc.
Here's the part that generates the n/v:
([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[1^11<<1]
In Firefox, ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]]) evaluates to
"function test() {
[native code]
}"
while in Chrome it is
"function test() { [native code] }"
1^11<<1 equals 23. So due to Firefox's extra whitespace, this isn't quite enough to get to the 'v', and is instead 'n'.
And this is why you shouldn't rely on Function#toString behavior. ;)
EDIT:
Finally I found a reasonably obfuscated cross-browser version:
[[]+1/!1][1^1][1>>1]+({}+[])[1<<1^11>>1]+([]+!!-[])[1<<1]+[/~/+{}][+!1][-~1<<1]+([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1^11<<1)+(parseInt("010")<10?(1+1+1+1):0)]+([,][~1]+[])[1-~1]+[[]+{}][!1.1%1][11111.1%11.1*111e11|!1]+(/1/+1/[1<1][1%1])[1^11]+[[],[]+{}][1][+1]+(/<</[1]+[])[1/1.1&1]
This replaces the n/v section with:
([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]])[(1^11<<1)+(parseInt("010")<10?(1+1+1+1):0)]
which exploits differences in parseInt (apparently Firefox parses numbers starting with 0 as octal, while Chrome doesn't) to add 4 in Firefox's case, thus getting 'v' from 'native' in both cases (I can't find another 'v' :P).
The parseInt looks a little out of place, but that's the best I can do for now.
For the general use-case, if character casing isn't a big concern, I might be inclined to cheat a little.
Create function "c" which turns a number 0 .. 25 into a character.
c=function(v){for(var i in window){for(var ci in i){if(parseInt(i[ci],(10+11+11)+(1<<1)+(1<<1))==(v+10)){return i[ci]}}}};
For performance reasons, pre-cache the letters, if you want.
l=[];for(var i=0; i<(11+11)+(1<<1)+(1<<1);i++){l[i]=c(i);}
In the Chrome console, the resulting array looks like this:
> l;
["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "K", "l", "m", "n", "o", "p", "q", "r", "S", "t", "u", "v", "w", "x", "y", "Z"]
So ... your v might be l[10+10+1].
Alternatively, a general solution like this:
p=(function(){10%11}+[])[1+11+(1<<1)]; // "%"
u=(function(){club=1}+[])[1+11+(1<<1)]; // "u"
vc=p+u+(0+[])+(0+[])+((111>>1)+11+10+[]); // "%u0076"
unescape(vc);
Or, for this specific problem, maybe just:
(function(){v=1}+[])[10+(1<<1)]; // "v"
This gives a v in Chrome:
Object.getOwnPropertyNames(Object)[17][3];
And this does it in Firefox:
Object.getOwnPropertyNames(Object)[9][3]
They both pull it out of Object.prototype.preventExtensions(), so you could probably find a cross-browser way to reference that method. (It's the only 17-character name in Object.Prototype for starters.)
Feel free to build a more-obfuscated version of this and take all the credit for yourself, I'm out of time ;)
In chrome, the expression ([]+/-/[(!!1+[])[1>>1]+(!!1+[])[1<<1^1]+(!1+[])[1|1<<1]+(!!1+[])[1^1]]) evaluates to "function test() { [native code] }", the [1^11<<1] evaluates to 23 (bitwise operators cause the variable to be truncated to 32 bits)
I have a very specific problem concerning a regular expression matching in Javascript. I'm trying to match a piece of source code, more specifically a portion here:
<TD WIDTH=100% ALIGN=right>World Boards | Olympa - Trade | <b>Bump when Yasir...</b></TD>
The part I'm trying to match is boardid=106121">Olympa - Trade</a>, the part I actually need is "Olympa". So I use the following line of JS code to get a match and have "Olympa" returned:
var world = document.documentElement.innerHTML.match('/boardid=[0-9]+">([A-Z][a-z]+)( - Trade){0,1}<\/a>/i')[1];
the ( - Trade) part is optional in my problem, hence the {0,1} in the regex.
There's also no easier way to narrow down the code by e.g. getElementsByTagName, so searching the complete source code is my only option.
Now here's the funny thing. I have used two online regex matchers (of which one was for JS-regex specifically) to test my regex against the complete source code. Both times, it had a match and returned "Olympa" exactly as it should have. However, when I have Chrome include the script on the actual page, it gives the following error:
Error in event handler for 'undefined': Cannot read property '1' of null TypeError: Cannot read property '1' of null
Obviously, the first part of my line returns "null" because it does not find a match, and taking [1] of "null" doesn't work.
I figured I might not be doing the match on the source code, but when I let the script output document.documentElement.innerHTML to the console, it outputs the complete source code.
I see no reason why this regex fails, so I must be overlooking something very silly. Does anyone else see the problem?
All help appreciated,
Kenneth
You're putting your regular expression inside a string. It should not be inside a string.
var world = document.documentElement.innerHTML.match(/boardid=[0-9]+">([A-Z][a-z]+)( - Trade){0,1}<\/a>/i)[1];
Another thing — it appears you have a document object, in which case all this HTML is already parsed for you, and you can take advantage of that instead of reinventing a fragile wheel.
var element = document.querySelector('a[href*="boardid="]');
var world = element.textContent;
(This assumes that you don't need <=IE8 support. If you do, there remains a better way, though.)
(P.S. ? is shorthand for {0,1}.)
I came across a strange behaviour when doing some regular expressions in JavaScript today (Firefox 3 on Windows Vista).
var str = "format_%A";
var format = /(?:^|\s)format_(.*?)(?:\s|$)/.exec(str);
console.log(format); // ["format_%A", "%A"]
console.log(format[0]); // "format_undefined"
console.log(format[1]); // Undefined
There's nothing wrong with the regular expression. As you can see, it has matched the correct part in the first console.log call.
Internet Explorer 7 and Chrome both behave as expected: format[1] returns "%A" (well, Internet Explorer 7 doing something right was a bit unexpected...)
Is this a bug in Firefox, or some "feature" I don't know about?
This is because console.log() works like printf(). The first argument to console.log() is actually a format string which may be followed with additional arguments. %A is a placeholder. For example:
console.log("My name is %A", "John"); // My name is "John"
See console.log() documentation for details. %A and any other undocumented placeholders seem to do the same as %o.
Seems like %A somehow translates into the string undefined.
Try escaping the %A part, I think that will solve the problem.