angularjs sanitize to remove only JS - javascript

I intend to allow users to input iframes, custom inlines styles and maybe other things.
But I would like to remove anything JS.
By using $sanitize I seem to remove too much.

If you only want to strip out script tags you should do something like this:
angular.module('app', ['ngSanitize'])
.directive('testDir', function() {
return {
restrict: 'A',
controller: function($scope, $sce) {
$scope.sanitizeIt = function() {
var replacer = /<script>.*(<\/?script>?)?/gi;
var stripped = $scope.html.replace(replacer, '');
$scope.sanitizedHtml = $sce.trustAsHtml(stripped);
};
$scope.$watch('html', $scope.sanitizeIt);
}
};
});
The regular expression will wipe out all script tags and $sce tells the application that you can trust the string that is stripped as HTML.
In your application you can then write something like this:
<body ng-app="app">
<div test-dir>
<textarea ng-model="html"></textarea>
<div ng-bind-html="sanitizedHtml"></div>
</div>
</body>
When you persist to the database, make sure you save the sanitized HTML string instead of the html one.
Here's more documentation on $sce:
https://docs.angularjs.org/api/ng/service/$sce
It's basically what $sanitize uses behind the scenes. NOTE: I have not tested this regular expression in browsers aside from Chrome, so you might have to do some of your own tweaking to get it to work to suit your needs. However, the idea is the same.

Related

Problems with forced escaping of characters when creating AngularJs element

I stumbled upon an issue with AngularJS and creation of elements.
In short: I need to create an element with html contents, but I do want to have the reference to that element at hand, so that I can perform some actions on it without actually rendering it in the browser.
I tried doing the following:
var template = angular.element('<div>' + templateString + '</div>');
$compile(template)($scope);
which kinda does the trick, but...
Some of these templates have logical expression in them. in example:
<div ng-if="a && b">something</div>
Unfortunately it seems that when I try to create such an element, regardless if I use $sce.trustAsHtml() with ng-bind-html or not the & characters within these conditions get escaped as &.
The html I get in the template looks like this:
<div ng-if="a && b">something</div>
Please take a look at the fiddle: https://jsfiddle.net/3uxdrp7b/1/
if this is a known issue - I'd be thankful for pointing me in the right direction, cause I've been banging my head against this for quite some time and I can't get it to work. Every example I looked at had a simple html inside the binding - it all works ok unless I use the cursed &.
The main issue is that the element is not updated right after compiling. It will contain the correct value after the current digest cycle is finished.
<!-- HTML -->
<div class="container" ng-app="app" ng-controller="DemoController">
<h3>Result:</h3> <span ng-bind-html="el"></span>
</div>
// js
var app = angular.module("app", ["ngSanitize"]);
app.controller("DemoController", ["$scope", "$compile", "$timeout",
function($scope, $compile, $timeout) {
$scope.a = true;
$scope.b = true;
let contents = "<div ng-if='a && b'>something</div>";
let compiled = $compile("<div>" + contents + "</div>")($scope);
$timeout(function(){
console.log(compiled.html());
$scope.el = compiled.html();
},0,true);
}]);
The fiddle: https://jsfiddle.net/vy9svmop/
It might be that in your case it is simpler to use the $interpolate service to recive the immediate result.

AngularJs: Find links with initial 'www' in the text and turns them into html links

I am using angular linky to find links in the text and convert them to url.
But linky doesn't support URL like following:
www.abc.com
abc.xyz
is there any other way to support those links?
linky filter already supports www.abc.com-like addresses.
And developing regexps by yourself to support abc.xyz is too complex and thankless job to do it alone. I would suggest to use mature third-party library for that, like Autolinker is.
Here is a simple module that may help to configure (with options supported by Autolinker) and wrap it into Angular filter
angular.module('linkier', ['ngSanitize'])
.constant('linkierConfig', {})
.filter('linkier', ['$window', '$sanitize', 'linkierConfig',
function ($window, $sanitize, linkierConfig) {
return function (input, config) {
if (!angular.isString(input))
return input;
config = angular.extend({}, linkierConfig, angular.isObject(config) ? config : {});
return $sanitize($window.Autolinker.link(input, config));
};
}]);
Finds links in text input and turns them into html links. Supports
http/https/ftp/mailto and plain email address links.
So it seems that it doesn't. You should create your own filter to solve this problem. Here's a template to get you started.
angular
.module('app.filters')
.filter('urlLink', urlLink);
function urlLink() {
return function(value) {
var result = '';
// ... logic ...
return result;
}
}
What is the best regular expression to check if a string is a valid URL?

Using blur.js with angularjs

I'm trying to make a blurred background efect with angular on a div, something like the image above, for this i'm using blur.js and everything work fine with jquery but the real question is this posible with angularjs, and what is the best way?
I'm really newbie with angular
thanks in advance
here another example of using blurjs http://www.designedbyaturtle.co.uk/2013/blur-a-background-image/
SOLVED (with help of gtramontina):
you can download the code here demo-blurjs-angular
The result (with my images)
This demo contain a issue (that is really of blur.js) like Edd Turtle mention on his post
Important Note: This technique doesn’t work with local files and has to run through a server, likewise if the background is hosted on the Amazon S3 service you will need to enable cross-domain calls (CORS)..
I suggest you create a directive, restricted to attribute maybe, and have that applying your effect.
Something like this (not tested - and assuming you've included, in this order, jquery, blur.js, then angular;
angular.module('myApp', []).
directive('blurred', function () {
var directive = { restrict: 'A' };
directive.compile = function compile (tElement) {
// taken from blur.js homepage
tElement.blurjs({
source: 'body',
radius: 7,
overlay: 'rgba(255,255,255,0.4)'
});
};
return directive;
});
Then use it:
<p blurred>lorem ipsum</p>
The point with the order I mentioned above, is that if you include jquery before angular, then angular uses it to wrap its dom elements, otherwise it'll use jqlite.
You need to write a angularjs directive for blur.js. Here is an example of how to write a directive for a query plugin:
http://amitgharat.wordpress.com/2013/02/03/an-approach-to-use-jquery-plugins-with-angularjs/

angularjs regex filter syntax highlighter

please take a look at this plunker: http://plnkr.co/edit/OIFu07GS0ZJQOdmpDnXB?p=preview
i am trying to create a syntax highlighter with angular. I have the filter working 80%. The regex is correct but the .replace() it "writes" the html as text on the pre and not rendering it as html.
take a look and you will understand what I am trying to do.
I know there are codemirror and ace directives but they are just too big for what I need.
anyone know how to fix it?
the correct output should be something like this:
<pre>
<span class="string">1</span>
<span class="string">2</span>
<span class="string">3</span>
#This is a mysql syntax highlighter
-- This is a comment/*
And this is a multi line comment
SELECT things FROM table;*/
</pre>
currently everything between pre is rendered as text.
any ideas?
thanx
I don't think you can do this with a filter, try a directive.
Below is an example, fairly straightforward. I first changed the filter to a service (though you can use the filter similarly with $filter if you want but I don't see why). Then I use $interpolate to create an interpolation function, described here:
Compiles a string with markup into an interpolation function. This service is used by the HTML $compile service for data binding. See $interpolateProvider for configuring the interpolation markup.
You can see in the example that the strings '1', '2' and '3' are highlighted because I added style="color:red", and they have the class as well.
Edit: edited solution with usage of ngModelController to make changes to the textarea appear in the element below with angular's data binding. Note the change to the snippet element: <snippet ng-model="txt">
var app = angular.module('plunker', ['syntax']);
app.controller('MainCtrl', function($scope) {
$scope.txt = "1 2 3 \n #This is a mysql syntax highlighter\n-- This is a comment/*\nAnd this is a multi line comment\nSELECT things FROM table;*/\nSELECT \nag.name AS agent, `d.date`, d.first_payment_date, d.account_number, ";
});
angular.module('syntax', [])
.service('formatter', function () {
return function (input) {
if (input) {
return input.replace(/(\d+)/g, "<span class=\"string\" style=\"color:red\">$1</span>");
}
}
})
.directive('snippet', function($timeout, $interpolate, formatter) {
return {
restrict: 'E',
template:'<pre><code></code></pre>',
replace:true,
require: '?ngModel',
link:function(scope, elm, attrs, ngModel){
ngModel.$render = function(){
var tmp = $interpolate(scope.txt)(scope);
elm.find('code').html(formatter(tmp));
}
}
};
});
http://plnkr.co/edit/783ML4Y2qH8oMLarf0kg?p=preview

Using AngularJS with innerHTML

I have some AngularJS stuff that holds a bunch of arrays and data. Once a user uploads a file, the file gets parsed up and saved into the scope with its different arrays. However, after all of this and the file is held in the scope, I try to update the innerHTML, but the AngularJS code does not work. I use ng-repeat to create a table based on the arrays, but it remains a single cell with content looking like {{column}} and the like.
I have had extreme difficulty using directives and templates because my index.html says that app and module, etc, are undefined when I do something such as app.directive(...
The significant parts of my index.html file include:
<html ng-app>
... //once a file is uploaded, total.js is called;
//this was so the app didn't try to run before a file was uploaded
<div id="someStuff">This will become a table once a file is uploaded</div>
This is a simple example of how my scope is set up in total.js:
function sheet($rootScope, $parse){
$rootScope.stuff = text;
//text is a variable that contains the file's contents as a string
};
document.getElementById('someStuff').innerHTML="<div ng-controller='sheet'>{{stuff}}</div>";
The HTML changes but instead of printing the file's contents, it only prints {{stuff}}.
How can I get the innerHTML to understand that it contains AngularJS, preferably without using a partial or a directive, unless you can thoroughly explain where I'd input it and the syntax of it.
Edit 1:
I have tried using $compile but it is marked as undefined. I looked at this to figure out the compile problem, but I don't understand rtcherry's syntax, and how I should apply it to my own code.
Edit 2:
I still receive $compile undefined errors when I include it like so:
function sheet($rootScope, $parse, $compile){...};
document.getElementById('someStuff').innerHTML=$compile("<div ng-controller='sheet'>
{{stuff}}</div>")(scope);
Edit 3:
While itcouldevenbeaboat's comment was extremely unhelpful, I decided I should perhaps show you the directive way I attempted to do it.
I included this code under my sheet function:
var app = angular.module('App', []);
app.directive('spreadsheeet', function($compile){
return{
templateUrl: innerHTML.html
}
});
Where innerHTML contains <div ng-controller='sheet'>{{stuff}}</div>and on index.html I've included <div spreadsheet></div>
With this, I receive no errors, but the text does not show up, neither as {{stuff}} or as the file's contents. Even when I do something simple, such as provide template: "<h2>Hello!</h2>" instead of a templateUrl, I cannot get Hello! to print.
It works for me
document.getElementById('someStuff').innerHTML = "<div ng-controller='sheet'>{{stuff}}</div>";
$compile( document.getElementById('someStuff') )($scope);
Simple solution (it will work 100%):
In controller, don't forget to inject $document in controller as a dependency, like this:
App.controller('indiaController', function ($scope, $document,$filter, $location) {
var text_element = angular.element($document[0].querySelector('#delhi');
text_element.html('your dynamic html placed here');
}

Categories

Resources