2016-04-28 17:50:03 -07:00
|
|
|
import {isPresent} from '../src/facade/lang';
|
2016-06-08 16:38:52 -07:00
|
|
|
|
|
|
|
import {AST} from './expression_parser/ast';
|
|
|
|
|
|
|
|
import {CompileDirectiveMetadata, CompileTokenMetadata, CompileProviderMetadata,} from './compile_metadata';
|
2015-10-07 09:34:21 -07:00
|
|
|
import {ParseSourceSpan} from './parse_util';
|
feat: security implementation in Angular 2.
Summary:
This adds basic security hooks to Angular 2.
* `SecurityContext` is a private API between core, compiler, and
platform-browser. `SecurityContext` communicates what context a value is used
in across template parser, compiler, and sanitization at runtime.
* `SanitizationService` is the bare bones interface to sanitize values for a
particular context.
* `SchemaElementRegistry.securityContext(tagName, attributeOrPropertyName)`
determines the security context for an attribute or property (it turns out
attributes and properties match for the purposes of sanitization).
Based on these hooks:
* `DomSchemaElementRegistry` decides what sanitization applies in a particular
context.
* `DomSanitizationService` implements `SanitizationService` and adds *Safe
Value*s, i.e. the ability to mark a value as safe and not requiring further
sanitization.
* `url_sanitizer` and `style_sanitizer` sanitize URLs and Styles, respectively
(surprise!).
`DomSanitizationService` is the default implementation bound for browser
applications, in the three contexts (browser rendering, web worker rendering,
server side rendering).
BREAKING CHANGES:
*** SECURITY WARNING ***
Angular 2 Release Candidates do not implement proper contextual escaping yet.
Make sure to correctly escape all values that go into the DOM.
*** SECURITY WARNING ***
Reviewers: IgorMinar
Differential Revision: https://reviews.angular.io/D103
2016-04-29 16:04:08 -07:00
|
|
|
import {SecurityContext} from '../core_private';
|
2015-08-25 15:36:02 -07:00
|
|
|
|
2015-12-03 15:49:09 -08:00
|
|
|
/**
|
|
|
|
* An Abstract Syntax Tree node representing part of a parsed Angular template.
|
|
|
|
*/
|
2015-08-25 15:36:02 -07:00
|
|
|
export interface TemplateAst {
|
2015-12-03 15:49:09 -08:00
|
|
|
/**
|
|
|
|
* The source span from which this node was parsed.
|
|
|
|
*/
|
2015-10-07 09:34:21 -07:00
|
|
|
sourceSpan: ParseSourceSpan;
|
2015-12-03 15:49:09 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Visit this node and possibly transform it.
|
|
|
|
*/
|
2015-09-01 16:24:23 -07:00
|
|
|
visit(visitor: TemplateAstVisitor, context: any): any;
|
2015-08-25 15:36:02 -07:00
|
|
|
}
|
|
|
|
|
2015-12-03 15:49:09 -08:00
|
|
|
/**
|
|
|
|
* A segment of text within the template.
|
|
|
|
*/
|
2015-08-25 15:36:02 -07:00
|
|
|
export class TextAst implements TemplateAst {
|
2016-06-08 16:38:52 -07:00
|
|
|
constructor(
|
|
|
|
public value: string, public ngContentIndex: number, public sourceSpan: ParseSourceSpan) {}
|
2015-09-01 16:24:23 -07:00
|
|
|
visit(visitor: TemplateAstVisitor, context: any): any { return visitor.visitText(this, context); }
|
2015-08-25 15:36:02 -07:00
|
|
|
}
|
|
|
|
|
2015-12-03 15:49:09 -08:00
|
|
|
/**
|
|
|
|
* A bound expression within the text of a template.
|
|
|
|
*/
|
2015-08-25 15:36:02 -07:00
|
|
|
export class BoundTextAst implements TemplateAst {
|
2016-06-08 16:38:52 -07:00
|
|
|
constructor(
|
|
|
|
public value: AST, public ngContentIndex: number, public sourceSpan: ParseSourceSpan) {}
|
2015-09-01 16:24:23 -07:00
|
|
|
visit(visitor: TemplateAstVisitor, context: any): any {
|
|
|
|
return visitor.visitBoundText(this, context);
|
|
|
|
}
|
2015-08-25 15:36:02 -07:00
|
|
|
}
|
|
|
|
|
2015-12-03 15:49:09 -08:00
|
|
|
/**
|
|
|
|
* A plain attribute on an element.
|
|
|
|
*/
|
2015-08-25 15:36:02 -07:00
|
|
|
export class AttrAst implements TemplateAst {
|
2015-10-07 09:34:21 -07:00
|
|
|
constructor(public name: string, public value: string, public sourceSpan: ParseSourceSpan) {}
|
2015-09-01 16:24:23 -07:00
|
|
|
visit(visitor: TemplateAstVisitor, context: any): any { return visitor.visitAttr(this, context); }
|
2015-08-25 15:36:02 -07:00
|
|
|
}
|
|
|
|
|
2015-12-03 15:49:09 -08:00
|
|
|
/**
|
|
|
|
* A binding for an element property (e.g. `[property]="expression"`).
|
|
|
|
*/
|
2015-08-27 16:29:02 -07:00
|
|
|
export class BoundElementPropertyAst implements TemplateAst {
|
2016-06-08 16:38:52 -07:00
|
|
|
constructor(
|
|
|
|
public name: string, public type: PropertyBindingType,
|
|
|
|
public securityContext: SecurityContext, public value: AST, public unit: string,
|
|
|
|
public sourceSpan: ParseSourceSpan) {}
|
2015-09-01 16:24:23 -07:00
|
|
|
visit(visitor: TemplateAstVisitor, context: any): any {
|
|
|
|
return visitor.visitElementProperty(this, context);
|
|
|
|
}
|
2015-08-25 15:36:02 -07:00
|
|
|
}
|
|
|
|
|
2015-12-03 15:49:09 -08:00
|
|
|
/**
|
|
|
|
* A binding for an element event (e.g. `(event)="handler()"`).
|
|
|
|
*/
|
2015-08-25 15:36:02 -07:00
|
|
|
export class BoundEventAst implements TemplateAst {
|
2016-06-08 16:38:52 -07:00
|
|
|
constructor(
|
|
|
|
public name: string, public target: string, public handler: AST,
|
|
|
|
public sourceSpan: ParseSourceSpan) {}
|
2015-09-01 16:24:23 -07:00
|
|
|
visit(visitor: TemplateAstVisitor, context: any): any {
|
|
|
|
return visitor.visitEvent(this, context);
|
|
|
|
}
|
2015-09-18 10:33:23 -07:00
|
|
|
get fullName() {
|
2015-09-11 13:37:05 -07:00
|
|
|
if (isPresent(this.target)) {
|
|
|
|
return `${this.target}:${this.name}`;
|
|
|
|
} else {
|
|
|
|
return this.name;
|
|
|
|
}
|
|
|
|
}
|
2015-08-25 15:36:02 -07:00
|
|
|
}
|
|
|
|
|
2015-12-03 15:49:09 -08:00
|
|
|
/**
|
2016-04-25 19:52:24 -07:00
|
|
|
* A reference declaration on an element (e.g. `let someName="expression"`).
|
|
|
|
*/
|
|
|
|
export class ReferenceAst implements TemplateAst {
|
2016-06-08 16:38:52 -07:00
|
|
|
constructor(
|
|
|
|
public name: string, public value: CompileTokenMetadata, public sourceSpan: ParseSourceSpan) {
|
|
|
|
}
|
2016-04-25 19:52:24 -07:00
|
|
|
visit(visitor: TemplateAstVisitor, context: any): any {
|
|
|
|
return visitor.visitReference(this, context);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A variable declaration on a <template> (e.g. `var-someName="someLocalName"`).
|
2015-12-03 15:49:09 -08:00
|
|
|
*/
|
2015-08-25 15:36:02 -07:00
|
|
|
export class VariableAst implements TemplateAst {
|
2015-10-07 09:34:21 -07:00
|
|
|
constructor(public name: string, public value: string, public sourceSpan: ParseSourceSpan) {}
|
2015-09-01 16:24:23 -07:00
|
|
|
visit(visitor: TemplateAstVisitor, context: any): any {
|
|
|
|
return visitor.visitVariable(this, context);
|
|
|
|
}
|
2015-08-25 15:36:02 -07:00
|
|
|
}
|
|
|
|
|
2015-12-03 15:49:09 -08:00
|
|
|
/**
|
|
|
|
* An element declaration in a template.
|
|
|
|
*/
|
2015-08-25 15:36:02 -07:00
|
|
|
export class ElementAst implements TemplateAst {
|
2016-06-08 16:38:52 -07:00
|
|
|
constructor(
|
|
|
|
public name: string, public attrs: AttrAst[], public inputs: BoundElementPropertyAst[],
|
|
|
|
public outputs: BoundEventAst[], public references: ReferenceAst[],
|
|
|
|
public directives: DirectiveAst[], public providers: ProviderAst[],
|
|
|
|
public hasViewContainer: boolean, public children: TemplateAst[],
|
|
|
|
public ngContentIndex: number, public sourceSpan: ParseSourceSpan) {}
|
2016-01-06 14:13:44 -08:00
|
|
|
|
2015-09-01 16:24:23 -07:00
|
|
|
visit(visitor: TemplateAstVisitor, context: any): any {
|
|
|
|
return visitor.visitElement(this, context);
|
|
|
|
}
|
2015-08-25 15:36:02 -07:00
|
|
|
}
|
|
|
|
|
2015-12-03 15:49:09 -08:00
|
|
|
/**
|
|
|
|
* A `<template>` element included in an Angular template.
|
|
|
|
*/
|
2015-08-25 15:36:02 -07:00
|
|
|
export class EmbeddedTemplateAst implements TemplateAst {
|
2016-06-08 16:38:52 -07:00
|
|
|
constructor(
|
|
|
|
public attrs: AttrAst[], public outputs: BoundEventAst[], public references: ReferenceAst[],
|
|
|
|
public variables: VariableAst[], public directives: DirectiveAst[],
|
|
|
|
public providers: ProviderAst[], public hasViewContainer: boolean,
|
|
|
|
public children: TemplateAst[], public ngContentIndex: number,
|
|
|
|
public sourceSpan: ParseSourceSpan) {}
|
2016-01-06 14:13:44 -08:00
|
|
|
|
2015-09-01 16:24:23 -07:00
|
|
|
visit(visitor: TemplateAstVisitor, context: any): any {
|
|
|
|
return visitor.visitEmbeddedTemplate(this, context);
|
|
|
|
}
|
2015-08-25 15:36:02 -07:00
|
|
|
}
|
|
|
|
|
2015-12-03 15:49:09 -08:00
|
|
|
/**
|
|
|
|
* A directive property with a bound value (e.g. `*ngIf="condition").
|
|
|
|
*/
|
2015-08-27 16:29:02 -07:00
|
|
|
export class BoundDirectivePropertyAst implements TemplateAst {
|
2016-06-08 16:38:52 -07:00
|
|
|
constructor(
|
|
|
|
public directiveName: string, public templateName: string, public value: AST,
|
|
|
|
public sourceSpan: ParseSourceSpan) {}
|
2015-09-01 16:24:23 -07:00
|
|
|
visit(visitor: TemplateAstVisitor, context: any): any {
|
|
|
|
return visitor.visitDirectiveProperty(this, context);
|
|
|
|
}
|
2015-08-27 16:29:02 -07:00
|
|
|
}
|
|
|
|
|
2015-12-03 15:49:09 -08:00
|
|
|
/**
|
|
|
|
* A directive declared on an element.
|
|
|
|
*/
|
2015-08-27 16:29:02 -07:00
|
|
|
export class DirectiveAst implements TemplateAst {
|
2016-06-08 16:38:52 -07:00
|
|
|
constructor(
|
|
|
|
public directive: CompileDirectiveMetadata, public inputs: BoundDirectivePropertyAst[],
|
|
|
|
public hostProperties: BoundElementPropertyAst[], public hostEvents: BoundEventAst[],
|
|
|
|
public sourceSpan: ParseSourceSpan) {}
|
2015-09-01 16:24:23 -07:00
|
|
|
visit(visitor: TemplateAstVisitor, context: any): any {
|
|
|
|
return visitor.visitDirective(this, context);
|
|
|
|
}
|
2015-08-27 16:29:02 -07:00
|
|
|
}
|
|
|
|
|
2016-01-06 14:13:44 -08:00
|
|
|
/**
|
|
|
|
* A provider declared on an element
|
|
|
|
*/
|
|
|
|
export class ProviderAst implements TemplateAst {
|
2016-06-08 16:38:52 -07:00
|
|
|
constructor(
|
|
|
|
public token: CompileTokenMetadata, public multiProvider: boolean, public eager: boolean,
|
|
|
|
public providers: CompileProviderMetadata[], public providerType: ProviderAstType,
|
|
|
|
public sourceSpan: ParseSourceSpan) {}
|
2016-01-06 14:13:44 -08:00
|
|
|
|
|
|
|
visit(visitor: TemplateAstVisitor, context: any): any {
|
|
|
|
// No visit method in the visitor for now...
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export enum ProviderAstType {
|
|
|
|
PublicService,
|
|
|
|
PrivateService,
|
|
|
|
Component,
|
|
|
|
Directive,
|
|
|
|
Builtin
|
|
|
|
}
|
|
|
|
|
2015-12-03 15:49:09 -08:00
|
|
|
/**
|
|
|
|
* Position where content is to be projected (instance of `<ng-content>` in a template).
|
|
|
|
*/
|
2015-08-25 15:36:02 -07:00
|
|
|
export class NgContentAst implements TemplateAst {
|
2016-06-08 16:38:52 -07:00
|
|
|
constructor(
|
|
|
|
public index: number, public ngContentIndex: number, public sourceSpan: ParseSourceSpan) {}
|
2015-09-01 16:24:23 -07:00
|
|
|
visit(visitor: TemplateAstVisitor, context: any): any {
|
|
|
|
return visitor.visitNgContent(this, context);
|
|
|
|
}
|
2015-08-25 15:36:02 -07:00
|
|
|
}
|
|
|
|
|
2015-12-03 15:49:09 -08:00
|
|
|
/**
|
|
|
|
* Enumeration of types of property bindings.
|
|
|
|
*/
|
2015-08-27 16:29:02 -07:00
|
|
|
export enum PropertyBindingType {
|
2015-12-03 15:49:09 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A normal binding to a property (e.g. `[property]="expression"`).
|
|
|
|
*/
|
2015-08-27 16:29:02 -07:00
|
|
|
Property,
|
2015-12-03 15:49:09 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A binding to an element attribute (e.g. `[attr.name]="expression"`).
|
|
|
|
*/
|
2015-08-27 16:29:02 -07:00
|
|
|
Attribute,
|
2015-12-03 15:49:09 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A binding to a CSS class (e.g. `[class.name]="condition"`).
|
|
|
|
*/
|
2015-08-27 16:29:02 -07:00
|
|
|
Class,
|
2015-12-03 15:49:09 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A binding to a style rule (e.g. `[style.rule]="expression"`).
|
|
|
|
*/
|
2016-05-25 12:46:22 -07:00
|
|
|
Style,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A binding to an animation reference (e.g. `[animate.key]="expression"`).
|
|
|
|
*/
|
|
|
|
Animation
|
2015-08-27 16:29:02 -07:00
|
|
|
}
|
|
|
|
|
2015-12-03 15:49:09 -08:00
|
|
|
/**
|
|
|
|
* A visitor for {@link TemplateAst} trees that will process each node.
|
|
|
|
*/
|
2015-08-25 15:36:02 -07:00
|
|
|
export interface TemplateAstVisitor {
|
2015-09-01 16:24:23 -07:00
|
|
|
visitNgContent(ast: NgContentAst, context: any): any;
|
|
|
|
visitEmbeddedTemplate(ast: EmbeddedTemplateAst, context: any): any;
|
|
|
|
visitElement(ast: ElementAst, context: any): any;
|
2016-04-25 19:52:24 -07:00
|
|
|
visitReference(ast: ReferenceAst, context: any): any;
|
2015-09-01 16:24:23 -07:00
|
|
|
visitVariable(ast: VariableAst, context: any): any;
|
|
|
|
visitEvent(ast: BoundEventAst, context: any): any;
|
|
|
|
visitElementProperty(ast: BoundElementPropertyAst, context: any): any;
|
|
|
|
visitAttr(ast: AttrAst, context: any): any;
|
|
|
|
visitBoundText(ast: BoundTextAst, context: any): any;
|
|
|
|
visitText(ast: TextAst, context: any): any;
|
|
|
|
visitDirective(ast: DirectiveAst, context: any): any;
|
|
|
|
visitDirectiveProperty(ast: BoundDirectivePropertyAst, context: any): any;
|
2015-08-25 15:36:02 -07:00
|
|
|
}
|
|
|
|
|
2015-12-03 15:49:09 -08:00
|
|
|
/**
|
|
|
|
* Visit every node in a list of {@link TemplateAst}s with the given {@link TemplateAstVisitor}.
|
|
|
|
*/
|
2016-06-08 16:38:52 -07:00
|
|
|
export function templateVisitAll(
|
|
|
|
visitor: TemplateAstVisitor, asts: TemplateAst[], context: any = null): any[] {
|
2016-06-08 15:45:15 -07:00
|
|
|
var result: any[] /** TODO #9100 */ = [];
|
2015-08-25 15:36:02 -07:00
|
|
|
asts.forEach(ast => {
|
2015-09-01 16:24:23 -07:00
|
|
|
var astResult = ast.visit(visitor, context);
|
2015-08-25 15:36:02 -07:00
|
|
|
if (isPresent(astResult)) {
|
|
|
|
result.push(astResult);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return result;
|
|
|
|
}
|