I'm actually working on a website in which I'll need to replace many words by something like for example: banana by ******.
I use a website with php and mysql, but I also use javascript.
I have in my database a table in which are banned words.
I'm receive this words in an array from my database. i'm looking for a function that will be able to replace this words in all tha page. i can not use function like ob start.
The best will be a function that check on body onload and replace words.
This is a rather difficult task to tackle because:
People will try to circumvent this system by replacing certain letter, such as "s" with "$", "a" with "#", or by misspelling words that can still be understood
How will you deal with words like "password" that contains an swear word?
I would recommend going with a service that already has this figured out:
http://www.webpurify.com/
Look at this SO post: How do you implement a good profanity filter?
I'm going to use CoffeeScript, you can compile to JavaScript here if you wish or just use this as pseudocode.
String::replaceAll = (a, b) ->
regExp = new RegExp(a, "ig")
#replace regExp, b
_stars = (string) ->
str = ""
for i in [0..string.length]
str = "#{str}*"
str
bannedWords = [ "bannedword", "anotherbannedword" ]
_formSubmitHandler = (data) ->
for bannedWord in bannedWords
data.userInput = data.userInput.replaceAll bannedWord, _stars(data.userInput)
If the page content is as well coming from the database, or being entered into the database. Why not filter it using php prior to it being inserted or when it is pulled using str_replace
// PREFERRED WAY
$filteredContent = str_replace($bannedlist, "**", $content2Filter);
Or if you are looking for a javascript version, then you would need to use either multiple str.replace or regex. Something like:
var search = "/word1|word2|word3/gi"; //This would be your array joined by a pipe delimiter
var ret=str.replace(search,'**');
I made a very simple censoring method for this. It will only track words you put into the array of bad words. I would suggest you use an advanced library for word censors.
censor.js
var censor = (function() {
function convertToAsterisk(word) {
var asteriskSentence = '';
for(var asterisks=0;asterisks<word.length;asterisks++) {
asteriskSentence+='*';
}
return asteriskSentence;
}
return function(sentence, bannedWords) {
sentence = sentence || undefined;
bannedWords = bannedWords || undefined;
if(sentence!==undefined && bannedWords!==undefined) {
for(var word=0;word<bannedWords.length;word++) {
sentence = sentence.replace(bannedWords[word], convertToAsterisk(bannedWords[word]));
}
}
return sentence;
};
})();
The method can be used like so:
var sentence = 'I like apples, grapes, and peaches. My buddy likes pears';
var bannedWords = [
'pears',
'peaches',
'grapes',
'apples'
];
sentence = censor(sentence, bannedWords);
This system does not protect bad words within other words, or tricky mispellings. Only the basics.
var str="badword";
var ret=str.replace("badword","*******");
And to detect length automatically (useful for function useage)
var str="badword";
var ret=str.replace("badword",function() {
var ret = ""
for(var loop = 0; loop < str.length; loop++) {
var ret = ret + "*"
}
return ret
});
Finally I find my own way to make this system it is an easy way and you don't need to change all the code for all your website just the page that needs to be censored.
As far as I'm concerned I uses thausands of pages but the things is that I have one main page that included others pages.
For poeple who may be interested. all you have to do is to put this code at the beginning of your page so after the just put this code <?php ob_start(); ?> at the end of the body, before just put this code `
<?php
//We get the content of the page
$content = ob_get_contents();
// and we replace all
$content = str_replace('naughty', '*****', $content);
/// / VERY important, we must finish the page or in any case include ob_end_clean () function before echo $ content as PHP code would be displayed also
ob_end_clean ();
echo $content;
?>
This is an easy way, but you can also do an array for all censored words.
Full disclosure, I wrote the plugin.
I've written a jQuery plugin that does what you're looking for. It is not completely water tight, and others can very easily circumvent the plugin by disabling javascript. If you'd like to try it out, here's a link.
http://profanityfilter.chaseflorell.com/
And here's some example code.
<div id="someDiv">swears are ass, but passwords are ok</div>
<script>
$('#someDiv').profanityFilter({
customSwears: ['ass']
});
</script>
Related
I am trying to create a very simplistic XSS detection system for a system I am currently developing. The system as it stands, allows users to submit posts with javascript embedded within the message. Here is what I currently have:-
var checkFor = "<script>";
alert(checkFor.indexOf("<script>") !== -1);
This doesn't really work that well at all. I need to write code that incorporates an array which contains the terms I am searching for [e.g - "<script>","</script>","alert("]
Any suggestions as to how this could be achieved using JavaScript/jQuery.
Thanks for checking this out. Many thanks :)
Replacing characters is a very fragile way to avoid XSS. (There are dozens of ways to get < in without typing the character -- like < Instead, HTML-encode your data. I use these functions:
var encode = function (data) {
var result = data;
if (data) {
result = $("<div />").html(data).text();
}
};
var decode = function (data) {
var result = data;
if (data) {
result = $("<div />").text(data).html();
}
};
As Explosion Pills said, if you're looking for cross–site exploits, you're probably best to either find one that's already been written or someone who can write one for you.
Anyway, to answer the question, regular expressions are not appropriate for parsing markup. If you have an HTML parser (client side is easy, server a little more difficult) you could insert the text as the innerHTML of an new element, then see if there are any child elements:
function mightBeMarkup(s) {
var d = document.createElement('div');
d.innerHTML = s;
return !!(d.getElementsByTagName('*').length);
}
Of course there still might be markup in the text, just that it's invalid so doesn't create elements. But combined with some other text, it might be valid markup.
The most effective way to prevent xss attacks is by replacing all <, > and & characters with
<, >, and &.
There is a javascript library from OWASP. I haven't worked with it yet so can't tell you anything about the quality. Here is the link: https://www.owasp.org/index.php/ESAPI_JavaScript_Readme
So let’s say the text KEYWORDANIMAL:(Cat) appears on a page. I want to search through the page for all instances of KEYWORDANIMAL, and then pull the actual animal, in this case Cat, into a variable to be used in another script that’ll pull in related content. I also want to replace KEYWORDANIMAL:(Cat) with an empty div with concatenated ID to be targeted by the other script (this other script is already working fine by itself).
I've been using info from several other threads here but just cannot make it all come together.
-Find text string using jQuery?
-Get text from character and after using jQuery
-How do I use JQuery to replace all occurring of a certain word in a webpage?
Here's what I have so far:
<p>Here is an animal: KEYWORDANIMAL(Cat)</p>
var findString = $('p:contains("KEYWORDANIMAL")').html();
var startIDString = findString.indexOf('(') + 1;
var endIDString = findString.indexOf(')');
var animalID = findString.substring(startIDString, endIDString);
var embedString1 = "<div id=\"";
var embedString2 = "\"></div>";
var embedStringFull = embedString1 + "animal" + animalID + embedString2;
alert(embedStringFull);
findString.each(function () {
var newDIV = $(this).html().replace('KEYWORDANIMAL', embedStringFull);
$(this).html(newDIV);
});
In fiddle form: http://jsfiddle.net/dC6bj/1/
I got the find part down (probably not very efficiently though), but I am clearly missing something on the replace.
If you absolutely have to do this with JavaScript, you can use a regex replacement function:
var animal_regex = /KEYWORDANIMAL\((.*?)\)/g;
$('p:contains("KEYWORDANIMAL")').each(function() {
var $this = $(this);
var html = $this.html().replace(animal_regex, function(match, name) {
return '<div id="animal' + name + '"></div>';
});
$this.html(html);
});
Demo: http://jsfiddle.net/dnuaL/
This should be done serverside, if possible.
For your third question on how toreplace all occurences of a certain word in a webpage use Regex.Replace like this:
var pagecontent = $('body').html();
var newcontent = Regex.Replace(pagecontent , #"[cat]", "dog");
&('body').html(newcontent);
Regex is the fastest solution for this kind of stuff.
My code example is a bit simple, it would also replace ocurrences within a tag.
or within a word for example in catamaran or .
To make it more perfect you could look for cat preceded by a space and followed by a space or a point or a comma. Read some regex tutorials for this. (It's really worth learning, once you know how to, you'll use it a lot)
Goodluck!
I am currently trying to code an input form where you can type and format a text for later use as XML entries. In order to make the HTML code XML-readable, I have to replace the code brackets with the corresponding symbol codes, i.e. < with < and > with >.
The formatted text gets transferred as HTML code with the variable inputtext, so we have for example the text
The <b>Genji</b> and the <b>Heike</b> waged a long and bloody war.
which needs to get converted into
The <b>Genji</b> and the <b>Heike</b> waged a long and bloody war.
I tried it with the .replace() function:
inputxml = inputxml.replace("<", "<");
inputxml = inputxml.replace(">", ">");
But this would just replace the first occurrence of the brackets. I'm pretty sure I need some sort of loop for this; I also tried using the each() function from jQuery (a friend recommended I looked at the jQuery package), but I'm still new to coding in general and I have troubles getting this to work.
How would you code a loop which would replace the code brackets within a variable as described above?
Additional information
You are, of course, right in the assumption that this is part of something larger. I am a graduate student in Japanese studies and currently, I am trying to visualize information about Japenese history in a more accessible way. For this, I am using the Simile Timeline API developed by MIT grad students. You can see a working test of a timeline on my homepage.
The Simile Timeline uses an API based on AJAX and Javascript. If you don't want to install the AJAX engine on your own server, you can implement the timeline API from the MIT. The data for the timeline is usually provided either by one or several XML files or JSON files. In my case, I use XML files; you can have a look at the XML structure in this example.
Within the timeline, there are so-called "events" on which you can click in order to reveal additional information within an info bubble popup. The text within those info bubbles originates from the XML source file. Now, if you want to do some HTML formatting within the info bubbles, you cannot use code bracket because those will just be displayed as plain text. It works if you use the symbol codes instead of the plain brackets, however.
The content for the timeline will be written by people absolutely and totally not accustomed to codified markup, i.e. historians, art historians, sociologists, among them several persons of age 50 and older. I have tried to explain to them how they have to format the XML file if they want to create a timeline, but they occasionally slip up and get frustrated when the timeline doesn't load because they forgot to close a bracket or to include an apostrophe.
In order to make it easier, I have tried making an easy-to-use input form where you can enter all the information and format the text WYSIWYG style and then have it converted into XML code which you just have to copy and paste into the XML source file. Most of it works, though I am still struggling with the conversion of the text markup in the main text field.
The conversion of the code brackets into symbol code is the last thing I needed to get working in order to have a working input form.
look here:
http://www.bradino.com/javascript/string-replace/
just use this regex to replace all:
str = str.replace(/\</g,"<") //for <
str = str.replace(/\>/g,">") //for >
To store an arbitrary string in XML, use the native XML capabilities of the browser. It will be a hell of a lot simpler that way, plus you will never have to think about the edge cases again (for example attribute values that contain quotes or pointy brackets).
A tip to think of when working with XML: Do never ever ever build XML from strings by concatenation if there is any way to avoid it. You will get yourself into trouble that way. There are APIs to handle XML, use them.
Going from your code, I would suggest the following:
$(function() {
$("#addbutton").click(function() {
var eventXml = XmlCreate("<event/>");
var $event = $(eventXml);
$event.attr("title", $("#titlefield").val());
$event.attr("start", [$("#bmonth").val(), $("#bday").val(), $("#byear").val()].join(" "));
if (parseInt($("#eyear").val()) > 0) {
$event.attr("end", [$("#emonth").val(), $("#eday").val(), $("#eyear").val()].join(" "));
$event.attr("isDuration", "true");
} else {
$event.attr("isDuration", "false");
}
$event.text( tinyMCE.activeEditor.getContent() );
$("#outputtext").val( XmlSerialize(eventXml) );
});
});
// helper function to create an XML DOM Document
function XmlCreate(xmlString) {
var x;
if (typeof DOMParser === "function") {
var p = new DOMParser();
x = p.parseFromString(xmlString,"text/xml");
} else {
x = new ActiveXObject("Microsoft.XMLDOM");
x.async = false;
x.loadXML(xmlString);
}
return x.documentElement;
}
// helper function to turn an XML DOM Document into a string
function XmlSerialize(xml) {
var s;
if (typeof XMLSerializer === "function") {
var x = new XMLSerializer();
s = x.serializeToString(xml);
} else {
s = xml.xml;
}
return s
}
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/replace
You might use a regular expression with the "g" (global match) flag.
var entities = {'<': '<', '>': '>'};
'<inputtext><anotherinputext>'.replace(
/[<>]/g, function (s) {
return entities[s];
}
);
You could also surround your XML entries with the following:
<![CDATA[...]]>
See example:
<xml>
<tag><![CDATA[The <b>Genji</b> and the <b>Heike</b> waged a long and bloody war.]]></tag>
</xml>
Wikipedia Article:
http://en.wikipedia.org/wiki/CDATA
What you really need, as mentioned in comments, is to XML-encode the string. If you absolutely want to do this is Javascript, have a look at the PHP.js function htmlentities.
I created a simple JS function to replace Greater Than and Less Than characters
Here is an example dirty string: < noreply#email.com >
Here is an example cleaned string: [ noreply#email.com ]
function RemoveGLthanChar(notes) {
var regex = /<[^>](.*?)>/g;
var strBlocks = notes.match(regex);
strBlocks.forEach(function (dirtyBlock) {
let cleanBlock = dirtyBlock.replace("<", "[").replace(">", "]");
notes = notes.replace(dirtyBlock, cleanBlock);
});
return notes;
}
Call it using
$('#form1').submit(function (e) {
e.preventDefault();
var dirtyBlock = $("#comments").val();
var cleanedBlock = RemoveGLthanChar(dirtyBlock);
$("#comments").val(cleanedBlock);
this.submit();
});
While browsing I came across this blog post about using the Wikipedia API from JavaScript, to link a single search term to it's definition. At the end of the blog post the author mentions possible extensions including:
A plugin which auto links terms to Wikipedia articles.
This fits the bill perfectly for a project requirement I'm working on, but sadly I lack the programming skills to extend the original source code. What I'd like is to have a pure JavaScript snippet I can add to a webpage, that links all the terms on that webpage that have an article on an internal wiki to that wiki.
I know this might be asking for much, but the code looks like it's nearly there, and I'd be willing to add a bounty if anyone will do the remaining work for that virtual credit.. ;) I also suspect this might be of value to a few others, as I've seen similar requests but no working implementation (that's a mere JavaScript (and therefore portable) library/snippet include).
Here's a sample of the original source code, I hope anyone is able to add to this or point me to what I'd need to add if I were to implement this myself (in which case I'll share the code if I manage to put something together).
<script type="text/javascript"><!--
var spellcheck = function (data) {
var found = false; var url=''; var text = data [0];
if (text != document.getElementById ('spellcheckinput').value)
return;
for (i=0; i<data [1].length; i++) {
if (text.toLowerCase () == data [1] [i].toLowerCase ()) {
found = true;
url ='http://en.wikipedia.org/wiki/' + text;
document.getElementById ('spellcheckresult').innerHTML = '<b style="color:green">Correct</b> - <a target="_top" href="' + url + '">link</a>';
}
}
if (! found)
document.getElementById ('spellcheckresult').innerHTML = '<b style="color:red">Incorrect</b>';
};
var getjs = function (value) {
if (! value)
return;
url = 'http://en.wikipedia.org/w/api.php?action=opensearch&search='+value+'&format=json&callback=spellcheck';
document.getElementById ('spellcheckresult').innerHTML = 'Checking ...';
var elem = document.createElement ('script');
elem.setAttribute ('src', url);
elem.setAttribute ('type','text/javascript');
document.getElementsByTagName ('head') [0].appendChild (elem);
};--></script>
<form action="#" method="get" onsubmit="return false">
<p>Enter a word - <input id="spellcheckinput" onkeyup="getjs (this.value);" type="text"> <span id="spellcheckresult"></span></p></form>
Update
As pointed out in the comments, both the time it would take to link all words and how to handle multiple word spanning article names were concerns of mine as well..
I'd think starting with single word articles would already cover a large percentage of the use cases, with maybe some performance benefits gained when skipping the 500 most common words in the English language, but still I'm uncertain how feasible this approach will be..
On the upside however this would all be client side, and some delay in linking terms is fully acceptable.
Alternatively searching for terms the mouse is hovering over / selected might be acceptable as well, but I'm unsure if this would decrease or increase complexity..
Update 2
'Pointy' explained below that this functionality could be achieved by altering some fairly standard highlighting scripts, after having obtained a list of article topics from api.php?action=query&list=allpages.
To reinterate: we're using an internal wiki, so the list of articles is likely limited, non ambiguous and domain specific enough to overcome some of the expected problems in matching words.
Since we've had some good suggestions so far, and a few workable ideas, I'm starting a bounty to see if I can get a few answers on this..
Perhaps something like this might help:
Assuming very simple HTML/Text like so:
<div id="theText">Testing the auto link system here...</div>
And two very small scripts.
dictionary.js sets up your list of your terms. My thought was that this could be generated in php by querying the articles database if you wanted. It also can be loaded cross domain (as it sets window.termsRE). If you don't need to generate the list from the database, you could also manually put it with termlinker.js.
This code that generates the RegExp assumes that your terms array contains properly formatted strings to match using Regular Expressions, so be sure to use \\ to escape []\.?*+|(){}^&
// dictionary.js - define some terms
var terms = ['testing', 'auto link'];
window.termsRE = new RegExp("\\b("+terms.join("|")+")\\b",'gi');
termlinker.js is just a simple regexp search replace on the defined terms. It could be an inline <script> too. requires that the dictionary.js has been loaded before you run it.
// termlinker.js - add some tags
var element = document.getElementById("theText");
element.innerHTML = element.innerHTML.replace(termsRE, function(term) {
return "<a href='http://en.wikipedia.org/wiki/"+escape(term)+"'>"+term+"</a>";
});
This simply searches for any words in the terms array and replaces them with a link to the term. Of course, it will also match properties and values inside HTML tags, which could break your markup a little.
All thrown together you get this (jsbin preview)
Using the API
Based off of the "minimum case" from before, here is the code sample for using the API to receive the list of words directly and the jsbin preview
// Utility Function
RegExp.escape = function(text) {
if (!arguments.callee.sRE) {
var specials = [
'/', '.', '*', '+', '?', '|',
'(', ')', '[', ']', '{', '}', '\\'
];
arguments.callee.sRE = new RegExp(
'(\\' + specials.join('|\\') + ')', 'g'
);
}
return text.replace(arguments.callee.sRE, '\\$1');
};
// JSONP Callback for receiving the API
function receiveAPI(data) {
var terms = [];
if (!data || !data['query'] || !data['query']['allpages']) return false;
var pages = data.query.allpages
for (var x in pages) {
terms.push(RegExp.escape(pages[x].title));
}
window.termsRE = new RegExp("\\b("+terms.reverse().join("|")+")\\b",'gi');
linkterms();
}
function linkterms() {
var element = document.getElementById("theText");
element.innerHTML = element.innerHTML.replace(termsRE, function(term) {
return "<a href='http://en.wikipedia.org/wiki/"+escape(term)+"'>"+term+"</a>";
});
}
// the apfrom=testing can be removed, it is only there so that
// we can get some useful terms near "testing" to work with.
// we are limited to 500 terms for the purpose of this demo:
url = 'http://en.wikipedia.org/w/api.php?action=query&list=allpages&aplimit=500&format=json&callback=receiveAPI' + '&apfrom=testing';
var elem = document.createElement('script');
elem.setAttribute('src', url);
elem.setAttribute('type','text/javascript');
document.getElementsByTagName('head')[0].appendChild (elem);
I am trying a new direction in Language Kits (or whatever you want to call those multi language text files with placeholders). Basically, I have text like this: Hello, my name is %0. Welcome to %1!. This would be my pText.
My pValues is an array whose values represent %0 and %1.
The following function should find %0 and replace it with pValues[0] and so on.
function _parseDialogMessage(pText, pValues) {
var result = pText;
for (var i=0; i<pValues.length; ++i) {
var regex = new RegExp('\%'+i, 'gi');
pText = pText.replace(regex, pValues[i]);
}
return result;
}
It all works except for the fact that it does not replace the placeholders %0 and %1. All Variables have the expected values but .replace doesn't seem to find my placeholders.
Any help?
Edit 1
Shame on me... -.-
You don't need "dynamic regex", since replace can take a function as argument:
function _parseDialogMessage(pText, pValues) {
return pText.replace(/%(\d+)/g, function (s, i) { return pValues[i]; });
}
(and you should return pText.)
You are returning the result variable which hold the initial values of the ptext parameter..
return the pText variable..
UUhm, you return result and not the replace pText
While you can't use any of their code unless you want to GPL your library, the manual for gnu's gettext covers the rationale behind a number of topics related to internationalization.
http://www.gnu.org/software/gettext/manual/gettext.html
edit : I know you're just looking for a magic regex, but it won't be enough.
easy example :
I have %n computers.
I have 1 computers.
Did you know arabic has a special tense for 2 things, and chinese no tense for the number of things referred to?