Skip to content
This repository has been archived by the owner on Sep 5, 2024. It is now read-only.

Commit

Permalink
fix(dialog): break content into textContent and htmlContent to
Browse files Browse the repository at this point in the history
help keep users from accidentally introducing an XSS vector.
  • Loading branch information
jelbourn committed Nov 13, 2015
1 parent fe84405 commit 6a56450
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 113 deletions.
1 change: 1 addition & 0 deletions config/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ module.exports = function(config) {
'node_modules/angular/angular.js',
'node_modules/angular-animate/angular-animate.js',
'node_modules/angular-aria/angular-aria.js',
'node_modules/angular-sanitize/angular-sanitize.js',
'node_modules/angular-mocks/angular-mocks.js',
'test/angular-material-mocks.js',
'test/angular-material-spec.js'
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"angular-animate": "1.4.7",
"angular-aria": "1.4.7",
"angular-messages": "1.4.7",
"angular-sanitize": "1.4.7",
"angular-mocks": "1.4.7",
"angular-route": "1.4.7",
"angularytics": "^0.3.0",
Expand Down Expand Up @@ -71,4 +72,4 @@
"merge-base": "git merge-base $(npm run -s current-branch) origin/master",
"squash": "git rebase -i $(npm run -s merge-base)"
}
}
}
4 changes: 2 additions & 2 deletions src/components/dialog/demoBasicUsage/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ angular.module('dialogDemo1', ['ngMaterial'])
.parent(angular.element(document.querySelector('#popupContainer')))
.clickOutsideToClose(true)
.title('This is an alert title')
.content('You can specify some description text in here.')
.textContent('You can specify some description text in here.')
.ariaLabel('Alert Dialog Demo')
.ok('Got it!')
.targetEvent(ev)
Expand All @@ -23,7 +23,7 @@ angular.module('dialogDemo1', ['ngMaterial'])
// Appending dialog to document.body to cover sidenav in docs app
var confirm = $mdDialog.confirm()
.title('Would you like to delete your debt?')
.content('All of the banks have agreed to <span class="debt-be-gone">forgive</span> you your debts.')
.textContent('All of the banks have agreed to forgive you your debts.')
.ariaLabel('Lucky day')
.targetEvent(ev)
.ok('Please do it!')
Expand Down
6 changes: 0 additions & 6 deletions src/components/dialog/demoBasicUsage/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@
position:relative;
}

.debt-be-gone {
font-weight: bold;
color:blue;
text-decoration: underline;
}

.footer {
width:100%;
text-align: center;
Expand Down
81 changes: 41 additions & 40 deletions src/components/dialog/dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -294,10 +294,12 @@ function MdDialogDirective($$rAF, $mdTheming, $mdDialog) {
*
* @returns {obj} an `$mdDialogPreset` with the chainable configuration methods:
*
* - $mdDialogPreset#title(string) - sets title to string
* - $mdDialogPreset#content(string) - sets content / message to string
* - $mdDialogPreset#ok(string) - sets okay button text to string
* - $mdDialogPreset#theme(string) - sets the theme of the dialog
* - $mdDialogPreset#title(string) - Sets the alert title.
* - $mdDialogPreset#textContent(string) - Sets the alert message.
* - $mdDialogPreset#htmlContent(string) - Sets the alert message as HTML. Requires ngSanitize
* module to be loaded. HTML is not run through Angular's compiler.
* - $mdDialogPreset#ok(string) - Sets the alert "Okay" button text.
* - $mdDialogPreset#theme(string) - Sets the theme of the alert dialog.
*
*/

Expand All @@ -313,11 +315,13 @@ function MdDialogDirective($$rAF, $mdTheming, $mdDialog) {
*
* Additionally, it supports the following methods:
*
* - $mdDialogPreset#title(string) - sets title to string
* - $mdDialogPreset#content(string) - sets content / message to string
* - $mdDialogPreset#ok(string) - sets okay button text to string
* - $mdDialogPreset#cancel(string) - sets cancel button text to string
* - $mdDialogPreset#theme(string) - sets the theme of the dialog
* - $mdDialogPreset#title(string) - Sets the confirm title.
* - $mdDialogPreset#textContent(string) - Sets the confirm message.
* - $mdDialogPreset#htmlContent(string) - Sets the confirm message as HTML. Requires ngSanitize
* module to be loaded. HTML is not run through Angular's compiler.
* - $mdDialogPreset#ok(string) - Sets the confirm "Okay" button text.
* - $mdDialogPreset#cancel(string) - Sets the confirm "Cancel" button text.
* - $mdDialogPreset#theme(string) - Sets the theme of the confirm dialog.
*
*/

Expand All @@ -332,7 +336,9 @@ function MdDialogDirective($$rAF, $mdTheming, $mdDialog) {
* `confirm()`, or an options object with the following properties:
* - `templateUrl` - `{string=}`: The url of a template that will be used as the content
* of the dialog.
* - `template` - `{string=}`: Same as templateUrl, except this is an actual template string.
* - `template` - `{string=}`: HTML template to show in the dialog. This **must** be trusted HTML
* with respect to Angular's [$sce service](https://docs.angularjs.org/api/ng/service/$sce).
* This template should **never** be constructed with any kind of user input or user data.
* - `autoWrap` - `{boolean=}`: Whether or not to automatically wrap the template with a
* `<md-dialog>` tag if one is not provided. Defaults to true. Can be disabled if you provide a
* custom dialog directive.
Expand Down Expand Up @@ -416,11 +422,11 @@ function MdDialogProvider($$interimElementProvider) {
options: dialogDefaultOptions
})
.addPreset('alert', {
methods: ['title', 'content', 'ariaLabel', 'ok', 'theme', 'css'],
methods: ['title', 'htmlContent', 'textContent', 'ariaLabel', 'ok', 'theme', 'css'],
options: advancedDialogOptions
})
.addPreset('confirm', {
methods: ['title', 'content', 'ariaLabel', 'ok', 'cancel', 'theme', 'css'],
methods: ['title', 'htmlContent', 'textContent', 'ariaLabel', 'ok', 'cancel', 'theme', 'css'],
options: advancedDialogOptions
});

Expand All @@ -431,7 +437,11 @@ function MdDialogProvider($$interimElementProvider) {
'<md-dialog md-theme="{{ dialog.theme }}" aria-label="{{ dialog.ariaLabel }}" ng-class="dialog.css">',
' <md-dialog-content class="md-dialog-content" role="document" tabIndex="-1">',
' <h2 class="md-title">{{ dialog.title }}</h2>',
' <div class="md-dialog-content-body" md-template="::dialog.mdContent"></div>',
' <div ng-if="::dialog.mdHtmlContent" class="md-dialog-content-body" ',
' ng-bind-html="::dialog.mdHtmlContent"></div>',
' <div ng-if="::!dialog.mdHtmlContent" class="md-dialog-content-body">',
' <p>{{::dialog.mdTextContent}}</p>',
' </div>',
' </md-dialog-content>',
' <md-dialog-actions>',
' <md-button ng-if="dialog.$type == \'confirm\'"' +
Expand Down Expand Up @@ -459,11 +469,12 @@ function MdDialogProvider($$interimElementProvider) {
}

/* @ngInject */
function dialogDefaultOptions($mdDialog, $mdAria, $mdUtil, $mdConstant, $animate, $document, $window, $rootElement, $log) {
function dialogDefaultOptions($mdDialog, $mdAria, $mdUtil, $mdConstant, $animate, $document, $window, $rootElement, $log, $injector) {
return {
hasBackdrop: true,
isolateScope: true,
onShow: onShow,
onShowing: beforeShow,
onRemove: onRemove,
clickOutsideToClose: false,
escapeToClose: true,
Expand All @@ -489,14 +500,25 @@ function MdDialogProvider($$interimElementProvider) {
}
};

/**
* Show method for dialogs
*/
function beforeShow(scope, element, options, controller) {
if (controller) {
controller.mdHtmlContent = controller.htmlContent || options.htmlContent || '';
controller.mdTextContent = controller.textContent || options.textContent || '';

if (controller.mdHtmlContent && !$injector.has('$sanitize')) {
throw Error('The ngSanitize module must be loaded in order to use htmlContent.');
}

if (controller.mdHtmlContent && controller.mdTextContent) {
throw Error('md-dialog cannot have both `htmlContent` and `textContent`');
}
}
}

/** Show method for dialogs */
function onShow(scope, element, options, controller) {
angular.element($document[0].body).addClass('md-dialog-is-showing');

wrapSimpleContent();

captureParentAndFromToElements(options);
configureAria(element.find('md-dialog'), options);
showBackdrop(scope, element, options);
Expand Down Expand Up @@ -548,27 +570,6 @@ function MdDialogProvider($$interimElementProvider) {
return angular.element(closeButton);
}
}

/**
* Wrap any simple content [specified via .content("")] in <p></p> tags.
* otherwise accept HTML content within the dialog content area...
* NOTE: Dialog uses the md-template directive to safely inject HTML content.
*/
function wrapSimpleContent() {
if ( controller ) {
var HTML_END_TAG = /<\/[\w-]*>/gm;
var content = controller.content || options.content || "";

var hasHTML = HTML_END_TAG.test(content);
if (!hasHTML) {
content = $mdUtil.supplant("<p>{0}</p>", [content]);
}

// Publish updated dialog content body... to be compiled by mdTemplate directive
controller.mdContent = content;
}
}

}

/**
Expand Down
Loading

0 comments on commit 6a56450

Please sign in to comment.