Return-Path: X-Original-To: apmail-flex-commits-archive@www.apache.org Delivered-To: apmail-flex-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 9B16C17BA2 for ; Fri, 25 Sep 2015 04:48:31 +0000 (UTC) Received: (qmail 92622 invoked by uid 500); 25 Sep 2015 04:48:31 -0000 Delivered-To: apmail-flex-commits-archive@flex.apache.org Received: (qmail 92495 invoked by uid 500); 25 Sep 2015 04:48:31 -0000 Mailing-List: contact commits-help@flex.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@flex.apache.org Delivered-To: mailing list commits@flex.apache.org Received: (qmail 92077 invoked by uid 99); 25 Sep 2015 04:48:30 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 25 Sep 2015 04:48:30 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 5AC8BE0A2B; Fri, 25 Sep 2015 04:48:30 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: aharui@apache.org To: commits@flex.apache.org Date: Fri, 25 Sep 2015 04:48:36 -0000 Message-Id: <15e1e5e5cded4753ad75e23b7df8f396@git.apache.org> In-Reply-To: <49b938a7b12e4c6f9aa6f1e51b6441d4@git.apache.org> References: <49b938a7b12e4c6f9aa6f1e51b6441d4@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [07/83] [abbrv] [partial] git commit: [flex-falcon] [refs/heads/develop] - Added GCL extern. http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/html/safestylesheet.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/html/safestylesheet.js b/externs/GCL/externs/goog/html/safestylesheet.js new file mode 100644 index 0000000..79e8b51 --- /dev/null +++ b/externs/GCL/externs/goog/html/safestylesheet.js @@ -0,0 +1,276 @@ +// Copyright 2014 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview The SafeStyleSheet type and its builders. + * + * TODO(user): Link to document stating type contract. + */ + +goog.provide('goog.html.SafeStyleSheet'); + +goog.require('goog.array'); +goog.require('goog.asserts'); +goog.require('goog.string'); +goog.require('goog.string.Const'); +goog.require('goog.string.TypedString'); + + + +/** + * A string-like object which represents a CSS style sheet and that carries the + * security type contract that its value, as a string, will not cause untrusted + * script execution (XSS) when evaluated as CSS in a browser. + * + * Instances of this type must be created via the factory method + * {@code goog.html.SafeStyleSheet.fromConstant} and not by invoking its + * constructor. The constructor intentionally takes no parameters and the type + * is immutable; hence only a default instance corresponding to the empty string + * can be obtained via constructor invocation. + * + * A SafeStyleSheet's string representation can safely be interpolated as the + * content of a style element within HTML. The SafeStyleSheet string should + * not be escaped before interpolation. + * + * Values of this type must be composable, i.e. for any two values + * {@code styleSheet1} and {@code styleSheet2} of this type, + * {@code goog.html.SafeStyleSheet.unwrap(styleSheet1) + + * goog.html.SafeStyleSheet.unwrap(styleSheet2)} must itself be a value that + * satisfies the SafeStyleSheet type constraint. This requirement implies that + * for any value {@code styleSheet} of this type, + * {@code goog.html.SafeStyleSheet.unwrap(styleSheet1)} must end in + * "beginning of rule" context. + + * A SafeStyleSheet can be constructed via security-reviewed unchecked + * conversions. In this case producers of SafeStyleSheet must ensure themselves + * that the SafeStyleSheet does not contain unsafe script. Note in particular + * that {@code <} is dangerous, even when inside CSS strings, and so should + * always be forbidden or CSS-escaped in user controlled input. For example, if + * {@code </style><script>evil</script>"} were interpolated + * inside a CSS string, it would break out of the context of the original + * style element and {@code evil} would execute. Also note that within an HTML + * style (raw text) element, HTML character references, such as + * {@code &lt;}, are not allowed. See + * http://www.w3.org/TR/html5/scripting-1.html#restrictions-for-contents-of-script-elements + * (similar considerations apply to the style element). + * + * @see goog.html.SafeStyleSheet#fromConstant + * @constructor + * @final + * @struct + * @implements {goog.string.TypedString} + */ +goog.html.SafeStyleSheet = function() { + /** + * The contained value of this SafeStyleSheet. The field has a purposely + * ugly name to make (non-compiled) code that attempts to directly access this + * field stand out. + * @private {string} + */ + this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_ = ''; + + /** + * A type marker used to implement additional run-time type checking. + * @see goog.html.SafeStyleSheet#unwrap + * @const + * @private + */ + this.SAFE_SCRIPT_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = + goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_; +}; + + +/** + * @override + * @const + */ +goog.html.SafeStyleSheet.prototype.implementsGoogStringTypedString = true; + + +/** + * Type marker for the SafeStyleSheet type, used to implement additional + * run-time type checking. + * @const + * @private + */ +goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {}; + + +/** + * Creates a new SafeStyleSheet object by concatenating values. + * @param {...(!goog.html.SafeStyleSheet|!Array)} + * var_args Values to concatenate. + * @return {!goog.html.SafeStyleSheet} + */ +goog.html.SafeStyleSheet.concat = function(var_args) { + var result = ''; + + /** + * @param {!goog.html.SafeStyleSheet|!Array} + * argument + */ + var addArgument = function(argument) { + if (goog.isArray(argument)) { + goog.array.forEach(argument, addArgument); + } else { + result += goog.html.SafeStyleSheet.unwrap(argument); + } + }; + + goog.array.forEach(arguments, addArgument); + return goog.html.SafeStyleSheet + .createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(result); +}; + + +/** + * Creates a SafeStyleSheet object from a compile-time constant string. + * + * {@code styleSheet} must not have any < characters in it, so that + * the syntactic structure of the surrounding HTML is not affected. + * + * @param {!goog.string.Const} styleSheet A compile-time-constant string from + * which to create a SafeStyleSheet. + * @return {!goog.html.SafeStyleSheet} A SafeStyleSheet object initialized to + * {@code styleSheet}. + */ +goog.html.SafeStyleSheet.fromConstant = function(styleSheet) { + var styleSheetString = goog.string.Const.unwrap(styleSheet); + if (styleSheetString.length === 0) { + return goog.html.SafeStyleSheet.EMPTY; + } + // > is a valid character in CSS selectors and there's no strict need to + // block it if we already block <. + goog.asserts.assert(!goog.string.contains(styleSheetString, '<'), + "Forbidden '<' character in style sheet string: " + styleSheetString); + return goog.html.SafeStyleSheet. + createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(styleSheetString); +}; + + +/** + * Returns this SafeStyleSheet's value as a string. + * + * IMPORTANT: In code where it is security relevant that an object's type is + * indeed {@code SafeStyleSheet}, use {@code goog.html.SafeStyleSheet.unwrap} + * instead of this method. If in doubt, assume that it's security relevant. In + * particular, note that goog.html functions which return a goog.html type do + * not guarantee the returned instance is of the right type. For example: + * + *
+ * var fakeSafeHtml = new String('fake');
+ * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype;
+ * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml);
+ * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by
+ * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml
+ * // instanceof goog.html.SafeHtml.
+ * 
+ * + * @see goog.html.SafeStyleSheet#unwrap + * @override + */ +goog.html.SafeStyleSheet.prototype.getTypedStringValue = function() { + return this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_; +}; + + +if (goog.DEBUG) { + /** + * Returns a debug string-representation of this value. + * + * To obtain the actual string value wrapped in a SafeStyleSheet, use + * {@code goog.html.SafeStyleSheet.unwrap}. + * + * @see goog.html.SafeStyleSheet#unwrap + * @override + */ + goog.html.SafeStyleSheet.prototype.toString = function() { + return 'SafeStyleSheet{' + + this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_ + '}'; + }; +} + + +/** + * Performs a runtime check that the provided object is indeed a + * SafeStyleSheet object, and returns its value. + * + * @param {!goog.html.SafeStyleSheet} safeStyleSheet The object to extract from. + * @return {string} The safeStyleSheet object's contained string, unless + * the run-time type check fails. In that case, {@code unwrap} returns an + * innocuous string, or, if assertions are enabled, throws + * {@code goog.asserts.AssertionError}. + */ +goog.html.SafeStyleSheet.unwrap = function(safeStyleSheet) { + // Perform additional Run-time type-checking to ensure that + // safeStyleSheet is indeed an instance of the expected type. This + // provides some additional protection against security bugs due to + // application code that disables type checks. + // Specifically, the following checks are performed: + // 1. The object is an instance of the expected type. + // 2. The object is not an instance of a subclass. + // 3. The object carries a type marker for the expected type. "Faking" an + // object requires a reference to the type marker, which has names intended + // to stand out in code reviews. + if (safeStyleSheet instanceof goog.html.SafeStyleSheet && + safeStyleSheet.constructor === goog.html.SafeStyleSheet && + safeStyleSheet.SAFE_SCRIPT_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ === + goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) { + return safeStyleSheet.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_; + } else { + goog.asserts.fail( + "expected object of type SafeStyleSheet, got '" + safeStyleSheet + + "'"); + return 'type_error:SafeStyleSheet'; + } +}; + + +/** + * Package-internal utility method to create SafeStyleSheet instances. + * + * @param {string} styleSheet The string to initialize the SafeStyleSheet + * object with. + * @return {!goog.html.SafeStyleSheet} The initialized SafeStyleSheet object. + * @package + */ +goog.html.SafeStyleSheet.createSafeStyleSheetSecurityPrivateDoNotAccessOrElse = + function(styleSheet) { + return new goog.html.SafeStyleSheet().initSecurityPrivateDoNotAccessOrElse_( + styleSheet); +}; + + +/** + * Called from createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(). This + * method exists only so that the compiler can dead code eliminate static + * fields (like EMPTY) when they're not accessed. + * @param {string} styleSheet + * @return {!goog.html.SafeStyleSheet} + * @private + */ +goog.html.SafeStyleSheet.prototype.initSecurityPrivateDoNotAccessOrElse_ = + function(styleSheet) { + this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_ = styleSheet; + return this; +}; + + +/** + * A SafeStyleSheet instance corresponding to the empty string. + * @const {!goog.html.SafeStyleSheet} + */ +goog.html.SafeStyleSheet.EMPTY = + goog.html.SafeStyleSheet. + createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(''); http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/html/safeurl.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/html/safeurl.js b/externs/GCL/externs/goog/html/safeurl.js new file mode 100644 index 0000000..6d2f871 --- /dev/null +++ b/externs/GCL/externs/goog/html/safeurl.js @@ -0,0 +1,431 @@ +// Copyright 2013 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview The SafeUrl type and its builders. + * + * TODO(user): Link to document stating type contract. + */ + +goog.provide('goog.html.SafeUrl'); + +goog.require('goog.asserts'); +goog.require('goog.fs.url'); +goog.require('goog.i18n.bidi.Dir'); +goog.require('goog.i18n.bidi.DirectionalString'); +goog.require('goog.string.Const'); +goog.require('goog.string.TypedString'); + + + +/** + * A string that is safe to use in URL context in DOM APIs and HTML documents. + * + * A SafeUrl is a string-like object that carries the security type contract + * that its value as a string will not cause untrusted script execution + * when evaluated as a hyperlink URL in a browser. + * + * Values of this type are guaranteed to be safe to use in URL/hyperlink + * contexts, such as, assignment to URL-valued DOM properties, or + * interpolation into a HTML template in URL context (e.g., inside a href + * attribute), in the sense that the use will not result in a + * Cross-Site-Scripting vulnerability. + * + * Note that, as documented in {@code goog.html.SafeUrl.unwrap}, this type's + * contract does not guarantee that instances are safe to interpolate into HTML + * without appropriate escaping. + * + * Note also that this type's contract does not imply any guarantees regarding + * the resource the URL refers to. In particular, SafeUrls are not + * safe to use in a context where the referred-to resource is interpreted as + * trusted code, e.g., as the src of a script tag. + * + * Instances of this type must be created via the factory methods + * ({@code goog.html.SafeUrl.fromConstant}, {@code goog.html.SafeUrl.sanitize}), + * etc and not by invoking its constructor. The constructor intentionally + * takes no parameters and the type is immutable; hence only a default instance + * corresponding to the empty string can be obtained via constructor invocation. + * + * @see goog.html.SafeUrl#fromConstant + * @see goog.html.SafeUrl#from + * @see goog.html.SafeUrl#sanitize + * @constructor + * @final + * @struct + * @implements {goog.i18n.bidi.DirectionalString} + * @implements {goog.string.TypedString} + */ +goog.html.SafeUrl = function() { + /** + * The contained value of this SafeUrl. The field has a purposely ugly + * name to make (non-compiled) code that attempts to directly access this + * field stand out. + * @private {string} + */ + this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ = ''; + + /** + * A type marker used to implement additional run-time type checking. + * @see goog.html.SafeUrl#unwrap + * @const + * @private + */ + this.SAFE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = + goog.html.SafeUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_; +}; + + +/** + * The innocuous string generated by goog.html.SafeUrl.sanitize when passed + * an unsafe URL. + * + * about:invalid is registered in + * http://www.w3.org/TR/css3-values/#about-invalid. + * http://tools.ietf.org/html/rfc6694#section-2.2.1 permits about URLs to + * contain a fragment, which is not to be considered when determining if an + * about URL is well-known. + * + * Using about:invalid seems preferable to using a fixed data URL, since + * browsers might choose to not report CSP violations on it, as legitimate + * CSS function calls to attr() can result in this URL being produced. It is + * also a standard URL which matches exactly the semantics we need: + * "The about:invalid URI references a non-existent document with a generic + * error condition. It can be used when a URI is necessary, but the default + * value shouldn't be resolveable as any type of document". + * + * @const {string} + */ +goog.html.SafeUrl.INNOCUOUS_STRING = 'about:invalid#zClosurez'; + + +/** + * @override + * @const + */ +goog.html.SafeUrl.prototype.implementsGoogStringTypedString = true; + + +/** + * Returns this SafeUrl's value a string. + * + * IMPORTANT: In code where it is security relevant that an object's type is + * indeed {@code SafeUrl}, use {@code goog.html.SafeUrl.unwrap} instead of this + * method. If in doubt, assume that it's security relevant. In particular, note + * that goog.html functions which return a goog.html type do not guarantee that + * the returned instance is of the right type. For example: + * + *
+ * var fakeSafeHtml = new String('fake');
+ * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype;
+ * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml);
+ * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by
+ * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml instanceof
+ * // goog.html.SafeHtml.
+ * 
+ * + * IMPORTANT: The guarantees of the SafeUrl type contract only extend to the + * behavior of browsers when interpreting URLs. Values of SafeUrl objects MUST + * be appropriately escaped before embedding in a HTML document. Note that the + * required escaping is context-sensitive (e.g. a different escaping is + * required for embedding a URL in a style property within a style + * attribute, as opposed to embedding in a href attribute). + * + * @see goog.html.SafeUrl#unwrap + * @override + */ +goog.html.SafeUrl.prototype.getTypedStringValue = function() { + return this.privateDoNotAccessOrElseSafeHtmlWrappedValue_; +}; + + +/** + * @override + * @const + */ +goog.html.SafeUrl.prototype.implementsGoogI18nBidiDirectionalString = true; + + +/** + * Returns this URLs directionality, which is always {@code LTR}. + * @override + */ +goog.html.SafeUrl.prototype.getDirection = function() { + return goog.i18n.bidi.Dir.LTR; +}; + + +if (goog.DEBUG) { + /** + * Returns a debug string-representation of this value. + * + * To obtain the actual string value wrapped in a SafeUrl, use + * {@code goog.html.SafeUrl.unwrap}. + * + * @see goog.html.SafeUrl#unwrap + * @override + */ + goog.html.SafeUrl.prototype.toString = function() { + return 'SafeUrl{' + this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ + + '}'; + }; +} + + +/** + * Performs a runtime check that the provided object is indeed a SafeUrl + * object, and returns its value. + * + * IMPORTANT: The guarantees of the SafeUrl type contract only extend to the + * behavior of browsers when interpreting URLs. Values of SafeUrl objects MUST + * be appropriately escaped before embedding in a HTML document. Note that the + * required escaping is context-sensitive (e.g. a different escaping is + * required for embedding a URL in a style property within a style + * attribute, as opposed to embedding in a href attribute). + * + * Note that the returned value does not necessarily correspond to the string + * with which the SafeUrl was constructed, since goog.html.SafeUrl.sanitize + * will percent-encode many characters. + * + * @param {!goog.html.SafeUrl} safeUrl The object to extract from. + * @return {string} The SafeUrl object's contained string, unless the run-time + * type check fails. In that case, {@code unwrap} returns an innocuous + * string, or, if assertions are enabled, throws + * {@code goog.asserts.AssertionError}. + */ +goog.html.SafeUrl.unwrap = function(safeUrl) { + // Perform additional Run-time type-checking to ensure that safeUrl is indeed + // an instance of the expected type. This provides some additional protection + // against security bugs due to application code that disables type checks. + // Specifically, the following checks are performed: + // 1. The object is an instance of the expected type. + // 2. The object is not an instance of a subclass. + // 3. The object carries a type marker for the expected type. "Faking" an + // object requires a reference to the type marker, which has names intended + // to stand out in code reviews. + if (safeUrl instanceof goog.html.SafeUrl && + safeUrl.constructor === goog.html.SafeUrl && + safeUrl.SAFE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ === + goog.html.SafeUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) { + return safeUrl.privateDoNotAccessOrElseSafeHtmlWrappedValue_; + } else { + goog.asserts.fail('expected object of type SafeUrl, got \'' + + safeUrl + '\''); + return 'type_error:SafeUrl'; + + } +}; + + +/** + * Creates a SafeUrl object from a compile-time constant string. + * + * Compile-time constant strings are inherently program-controlled and hence + * trusted. + * + * @param {!goog.string.Const} url A compile-time-constant string from which to + * create a SafeUrl. + * @return {!goog.html.SafeUrl} A SafeUrl object initialized to {@code url}. + */ +goog.html.SafeUrl.fromConstant = function(url) { + return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse( + goog.string.Const.unwrap(url)); +}; + + +/** + * A pattern that matches Blob types that can have SafeUrls created from + * URL.createObjectURL(blob). Only matches image types, currently. + * @const + * @private + */ +goog.html.SAFE_BLOB_TYPE_PATTERN_ = + /^image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)$/i; + + +/** + * Creates a SafeUrl wrapping a blob URL for the given {@code blob}. The + * blob URL is created with {@code URL.createObjectURL}. If the MIME type + * for {@code blob} is not of a known safe image MIME type, then the + * SafeUrl will wrap {@link #INNOCUOUS_STRING}. + * @see http://www.w3.org/TR/FileAPI/#url + * @param {!Blob} blob + * @return {!goog.html.SafeUrl} The blob URL, or an innocuous string wrapped + * as a SafeUrl. + */ +goog.html.SafeUrl.fromBlob = function(blob) { + var url = goog.html.SAFE_BLOB_TYPE_PATTERN_.test(blob.type) ? + goog.fs.url.createObjectUrl(blob) : goog.html.SafeUrl.INNOCUOUS_STRING; + return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url); +}; + + +/** + * A pattern that recognizes a commonly useful subset of URLs that satisfy + * the SafeUrl contract. + * + * This regular expression matches a subset of URLs that will not cause script + * execution if used in URL context within a HTML document. Specifically, this + * regular expression matches if (comment from here on and regex copied from + * Soy's EscapingConventions): + * (1) Either a protocol in a whitelist (http, https, mailto or ftp). + * (2) or no protocol. A protocol must be followed by a colon. The below + * allows that by allowing colons only after one of the characters [/?#]. + * A colon after a hash (#) must be in the fragment. + * Otherwise, a colon after a (?) must be in a query. + * Otherwise, a colon after a single solidus (/) must be in a path. + * Otherwise, a colon after a double solidus (//) must be in the authority + * (before port). + * + * The pattern disallows &, used in HTML entity declarations before + * one of the characters in [/?#]. This disallows HTML entities used in the + * protocol name, which should never happen, e.g. "http" for "http". + * It also disallows HTML entities in the first path part of a relative path, + * e.g. "foo<bar/baz". Our existing escaping functions should not produce + * that. More importantly, it disallows masking of a colon, + * e.g. "javascript:...". + * + * @private + * @const {!RegExp} + */ +goog.html.SAFE_URL_PATTERN_ = + /^(?:(?:https?|mailto|ftp):|[^&:/?#]*(?:[/?#]|$))/i; + + +/** + * Creates a SafeUrl object from {@code url}. If {@code url} is a + * goog.html.SafeUrl then it is simply returned. Otherwise the input string is + * validated to match a pattern of commonly used safe URLs. The string is + * converted to UTF-8 and non-whitelisted characters are percent-encoded. The + * string wrapped by the created SafeUrl will thus contain only ASCII printable + * characters. + * + * {@code url} may be a URL with the http, https, mailto or ftp scheme, + * or a relative URL (i.e., a URL without a scheme; specifically, a + * scheme-relative, absolute-path-relative, or path-relative URL). + * + * {@code url} is converted to UTF-8 and non-whitelisted characters are + * percent-encoded. Whitelisted characters are '%' and, from RFC 3986, + * unreserved characters and reserved characters, with the exception of '\'', + * '(' and ')'. This ensures the the SafeUrl contains only ASCII-printable + * characters and reduces the chance of security bugs were it to be + * interpolated into a specific context without the necessary escaping. + * + * If {@code url} fails validation or does not UTF-16 decode correctly + * (JavaScript strings are UTF-16 encoded), this function returns a SafeUrl + * object containing an innocuous string, goog.html.SafeUrl.INNOCUOUS_STRING. + * + * @see http://url.spec.whatwg.org/#concept-relative-url + * @param {string|!goog.string.TypedString} url The URL to validate. + * @return {!goog.html.SafeUrl} The validated URL, wrapped as a SafeUrl. + */ +goog.html.SafeUrl.sanitize = function(url) { + if (url instanceof goog.html.SafeUrl) { + return url; + } + else if (url.implementsGoogStringTypedString) { + url = url.getTypedStringValue(); + } else { + url = String(url); + } + if (!goog.html.SAFE_URL_PATTERN_.test(url)) { + url = goog.html.SafeUrl.INNOCUOUS_STRING; + } else { + url = goog.html.SafeUrl.normalize_(url); + } + return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url); +}; + + +/** + * Normalizes {@code url} the UTF-8 encoding of url, using a whitelist of + * characters. Whitelisted characters are not percent-encoded. + * @param {string} url The URL to normalize. + * @return {string} The normalized URL. + * @private + */ +goog.html.SafeUrl.normalize_ = function(url) { + try { + var normalized = encodeURI(url); + } catch (e) { // Happens if url contains invalid surrogate sequences. + return goog.html.SafeUrl.INNOCUOUS_STRING; + } + + return normalized.replace( + goog.html.SafeUrl.NORMALIZE_MATCHER_, + function(match) { + return goog.html.SafeUrl.NORMALIZE_REPLACER_MAP_[match]; + }); +}; + + +/** + * Matches characters and strings which need to be replaced in the string + * generated by encodeURI. Specifically: + * + * - '\'', '(' and ')' are not encoded. They are part of the reserved + * characters group in RFC 3986 but only appear in the obsolete mark + * production in Appendix D.2 of RFC 3986, so they can be encoded without + * changing semantics. + * - '[' and ']' are encoded by encodeURI, despite being reserved characters + * which can be used to represent IPv6 addresses. So they need to be decoded. + * - '%' is encoded by encodeURI. However, encoding '%' characters that are + * already part of a valid percent-encoded sequence changes the semantics of a + * URL, and hence we need to preserve them. Note that this may allow + * non-encoded '%' characters to remain in the URL (i.e., occurrences of '%' + * that are not part of a valid percent-encoded sequence, for example, + * 'ab%xy'). + * + * @const {!RegExp} + * @private + */ +goog.html.SafeUrl.NORMALIZE_MATCHER_ = /[()']|%5B|%5D|%25/g; + + +/** + * Map of replacements to be done in string generated by encodeURI. + * @const {!Object} + * @private + */ +goog.html.SafeUrl.NORMALIZE_REPLACER_MAP_ = { + '\'': '%27', + '(': '%28', + ')': '%29', + '%5B': '[', + '%5D': ']', + '%25': '%' +}; + + +/** + * Type marker for the SafeUrl type, used to implement additional run-time + * type checking. + * @const + * @private + */ +goog.html.SafeUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {}; + + +/** + * Package-internal utility method to create SafeUrl instances. + * + * @param {string} url The string to initialize the SafeUrl object with. + * @return {!goog.html.SafeUrl} The initialized SafeUrl object. + * @package + */ +goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse = function( + url) { + var safeUrl = new goog.html.SafeUrl(); + safeUrl.privateDoNotAccessOrElseSafeHtmlWrappedValue_ = url; + return safeUrl; +}; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/html/silverlight.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/html/silverlight.js b/externs/GCL/externs/goog/html/silverlight.js new file mode 100644 index 0000000..6aed4e2 --- /dev/null +++ b/externs/GCL/externs/goog/html/silverlight.js @@ -0,0 +1,92 @@ +// Copyright 2014 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/** + * @fileoverview SafeHtml factory methods for creating object tags for + * loading Silverlight files. + */ + +goog.provide('goog.html.silverlight'); + +goog.require('goog.html.SafeHtml'); +goog.require('goog.html.TrustedResourceUrl'); +goog.require('goog.html.flash'); +goog.require('goog.string.Const'); + + +/** + * Attributes and param tag name attributes not allowed to be overriden + * when calling createObjectForSilverlight(). + * + * While values that should be specified as params are probably not + * recognized as attributes, we block them anyway just to be sure. + * @const {!Array} + * @private + */ +goog.html.silverlight.FORBIDDEN_ATTRS_AND_PARAMS_ON_SILVERLIGHT_ = [ + 'data', // Always set to a fixed value. + 'source', // Specifies the URL for the Silverlight file. + 'type', // Always set to a fixed value. + 'typemustmatch' // Always set to a fixed value. +]; + + +/** + * Creates a SafeHtml representing an object tag, for loading Silverlight files. + * + * The following attributes are set to these fixed values: + * - data: data:application/x-silverlight-2, + * - type: application/x-silverlight-2 + * - typemustmatch: "" (the empty string, meaning true for a boolean attribute) + * + * @param {!goog.html.TrustedResourceUrl} source The value of the source param. + * @param {!Object=} opt_params Mapping used to generate child + * param tags. Each tag has a name and value attribute, as defined in + * mapping. Only names consisting of [a-zA-Z0-9-] are allowed. Value of + * null or undefined causes the param tag to be omitted. + * @param {!Object=} + * opt_attributes Mapping from other attribute names to their values. Only + * attribute names consisting of [a-zA-Z0-9-] are allowed. Value of null or + * undefined causes the attribute to be omitted. + * @return {!goog.html.SafeHtml} The SafeHtml content with the object tag. + * @throws {Error} If invalid attribute or param name, or attribute or param + * value is provided. Also if opt_attributes or opt_params contains any of + * the attributes set to fixed values, documented above, or contains source. + * + */ +goog.html.silverlight.createObject = function( + source, opt_params, opt_attributes) { + goog.html.flash.verifyKeysNotInMaps( + goog.html.silverlight.FORBIDDEN_ATTRS_AND_PARAMS_ON_SILVERLIGHT_, + opt_attributes, + opt_params); + + // We don't set default for Silverlight's EnableHtmlAccess and + // AllowHtmlPopupwindow because their default changes depending on whether + // a file loaded from the same domain. + var paramTags = goog.html.flash.combineParams( + {'source': source}, opt_params); + var fixedAttributes = { + 'data': goog.html.TrustedResourceUrl.fromConstant( + goog.string.Const.from('data:application/x-silverlight-2,')), + 'type': 'application/x-silverlight-2', + 'typemustmatch': '' + }; + var attributes = goog.html.SafeHtml.combineAttributes( + fixedAttributes, {}, opt_attributes); + + return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse( + 'object', attributes, paramTags); +}; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/html/trustedresourceurl.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/html/trustedresourceurl.js b/externs/GCL/externs/goog/html/trustedresourceurl.js new file mode 100644 index 0000000..e7c7bf5 --- /dev/null +++ b/externs/GCL/externs/goog/html/trustedresourceurl.js @@ -0,0 +1,224 @@ +// Copyright 2013 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview The TrustedResourceUrl type and its builders. + * + * TODO(user): Link to document stating type contract. + */ + +goog.provide('goog.html.TrustedResourceUrl'); + +goog.require('goog.asserts'); +goog.require('goog.i18n.bidi.Dir'); +goog.require('goog.i18n.bidi.DirectionalString'); +goog.require('goog.string.Const'); +goog.require('goog.string.TypedString'); + + + +/** + * A URL which is under application control and from which script, CSS, and + * other resources that represent executable code, can be fetched. + * + * Given that the URL can only be constructed from strings under application + * control and is used to load resources, bugs resulting in a malformed URL + * should not have a security impact and are likely to be easily detectable + * during testing. Given the wide number of non-RFC compliant URLs in use, + * stricter validation could prevent some applications from being able to use + * this type. + * + * Instances of this type must be created via the factory method, + * ({@code goog.html.TrustedResourceUrl.fromConstant}), and not by invoking its + * constructor. The constructor intentionally takes no parameters and the type + * is immutable; hence only a default instance corresponding to the empty + * string can be obtained via constructor invocation. + * + * @see goog.html.TrustedResourceUrl#fromConstant + * @constructor + * @final + * @struct + * @implements {goog.i18n.bidi.DirectionalString} + * @implements {goog.string.TypedString} + */ +goog.html.TrustedResourceUrl = function() { + /** + * The contained value of this TrustedResourceUrl. The field has a purposely + * ugly name to make (non-compiled) code that attempts to directly access this + * field stand out. + * @private {string} + */ + this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ = ''; + + /** + * A type marker used to implement additional run-time type checking. + * @see goog.html.TrustedResourceUrl#unwrap + * @const + * @private + */ + this.TRUSTED_RESOURCE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = + goog.html.TrustedResourceUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_; +}; + + +/** + * @override + * @const + */ +goog.html.TrustedResourceUrl.prototype.implementsGoogStringTypedString = true; + + +/** + * Returns this TrustedResourceUrl's value as a string. + * + * IMPORTANT: In code where it is security relevant that an object's type is + * indeed {@code TrustedResourceUrl}, use + * {@code goog.html.TrustedResourceUrl.unwrap} instead of this method. If in + * doubt, assume that it's security relevant. In particular, note that + * goog.html functions which return a goog.html type do not guarantee that + * the returned instance is of the right type. For example: + * + *
+ * var fakeSafeHtml = new String('fake');
+ * fakeSafeHtml.__proto__ = goog.html.SafeHtml.prototype;
+ * var newSafeHtml = goog.html.SafeHtml.htmlEscape(fakeSafeHtml);
+ * // newSafeHtml is just an alias for fakeSafeHtml, it's passed through by
+ * // goog.html.SafeHtml.htmlEscape() as fakeSafeHtml instanceof
+ * // goog.html.SafeHtml.
+ * 
+ * + * @see goog.html.TrustedResourceUrl#unwrap + * @override + */ +goog.html.TrustedResourceUrl.prototype.getTypedStringValue = function() { + return this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_; +}; + + +/** + * @override + * @const + */ +goog.html.TrustedResourceUrl.prototype.implementsGoogI18nBidiDirectionalString = + true; + + +/** + * Returns this URLs directionality, which is always {@code LTR}. + * @override + */ +goog.html.TrustedResourceUrl.prototype.getDirection = function() { + return goog.i18n.bidi.Dir.LTR; +}; + + +if (goog.DEBUG) { + /** + * Returns a debug string-representation of this value. + * + * To obtain the actual string value wrapped in a TrustedResourceUrl, use + * {@code goog.html.TrustedResourceUrl.unwrap}. + * + * @see goog.html.TrustedResourceUrl#unwrap + * @override + */ + goog.html.TrustedResourceUrl.prototype.toString = function() { + return 'TrustedResourceUrl{' + + this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ + '}'; + }; +} + + +/** + * Performs a runtime check that the provided object is indeed a + * TrustedResourceUrl object, and returns its value. + * + * @param {!goog.html.TrustedResourceUrl} trustedResourceUrl The object to + * extract from. + * @return {string} The trustedResourceUrl object's contained string, unless + * the run-time type check fails. In that case, {@code unwrap} returns an + * innocuous string, or, if assertions are enabled, throws + * {@code goog.asserts.AssertionError}. + */ +goog.html.TrustedResourceUrl.unwrap = function(trustedResourceUrl) { + // Perform additional Run-time type-checking to ensure that + // trustedResourceUrl is indeed an instance of the expected type. This + // provides some additional protection against security bugs due to + // application code that disables type checks. + // Specifically, the following checks are performed: + // 1. The object is an instance of the expected type. + // 2. The object is not an instance of a subclass. + // 3. The object carries a type marker for the expected type. "Faking" an + // object requires a reference to the type marker, which has names intended + // to stand out in code reviews. + if (trustedResourceUrl instanceof goog.html.TrustedResourceUrl && + trustedResourceUrl.constructor === goog.html.TrustedResourceUrl && + trustedResourceUrl + .TRUSTED_RESOURCE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ === + goog.html.TrustedResourceUrl + .TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_) { + return trustedResourceUrl + .privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_; + } else { + goog.asserts.fail('expected object of type TrustedResourceUrl, got \'' + + trustedResourceUrl + '\''); + return 'type_error:TrustedResourceUrl'; + + } +}; + + +/** + * Creates a TrustedResourceUrl object from a compile-time constant string. + * + * Compile-time constant strings are inherently program-controlled and hence + * trusted. + * + * @param {!goog.string.Const} url A compile-time-constant string from which to + * create a TrustedResourceUrl. + * @return {!goog.html.TrustedResourceUrl} A TrustedResourceUrl object + * initialized to {@code url}. + */ +goog.html.TrustedResourceUrl.fromConstant = function(url) { + return goog.html.TrustedResourceUrl + .createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse( + goog.string.Const.unwrap(url)); +}; + + +/** + * Type marker for the TrustedResourceUrl type, used to implement additional + * run-time type checking. + * @const + * @private + */ +goog.html.TrustedResourceUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {}; + + +/** + * Package-internal utility method to create TrustedResourceUrl instances. + * + * @param {string} url The string to initialize the TrustedResourceUrl object + * with. + * @return {!goog.html.TrustedResourceUrl} The initialized TrustedResourceUrl + * object. + * @package + */ +goog.html.TrustedResourceUrl. + createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse = function(url) { + var trustedResourceUrl = new goog.html.TrustedResourceUrl(); + trustedResourceUrl.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ = + url; + return trustedResourceUrl; +}; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/html/uncheckedconversions.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/html/uncheckedconversions.js b/externs/GCL/externs/goog/html/uncheckedconversions.js new file mode 100644 index 0000000..a1a5a9a --- /dev/null +++ b/externs/GCL/externs/goog/html/uncheckedconversions.js @@ -0,0 +1,231 @@ +// Copyright 2013 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Unchecked conversions to create values of goog.html types from + * plain strings. Use of these functions could potentially result in instances + * of goog.html types that violate their type contracts, and hence result in + * security vulnerabilties. + * + * Therefore, all uses of the methods herein must be carefully security + * reviewed. Avoid use of the methods in this file whenever possible; instead + * prefer to create instances of goog.html types using inherently safe builders + * or template systems. + * + * + * @visibility {//closure/goog/html:approved_for_unchecked_conversion} + * @visibility {//closure/goog/bin/sizetests:__pkg__} + */ + + +goog.provide('goog.html.uncheckedconversions'); + +goog.require('goog.asserts'); +goog.require('goog.html.SafeHtml'); +goog.require('goog.html.SafeScript'); +goog.require('goog.html.SafeStyle'); +goog.require('goog.html.SafeStyleSheet'); +goog.require('goog.html.SafeUrl'); +goog.require('goog.html.TrustedResourceUrl'); +goog.require('goog.string'); +goog.require('goog.string.Const'); + + +/** + * Performs an "unchecked conversion" to SafeHtml from a plain string that is + * known to satisfy the SafeHtml type contract. + * + * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure + * that the value of {@code html} satisfies the SafeHtml type contract in all + * possible program states. + * + * + * @param {!goog.string.Const} justification A constant string explaining why + * this use of this method is safe. May include a security review ticket + * number. + * @param {string} html A string that is claimed to adhere to the SafeHtml + * contract. + * @param {?goog.i18n.bidi.Dir=} opt_dir The optional directionality of the + * SafeHtml to be constructed. A null or undefined value signifies an + * unknown directionality. + * @return {!goog.html.SafeHtml} The value of html, wrapped in a SafeHtml + * object. + * @suppress {visibility} For access to SafeHtml.create... Note that this + * use is appropriate since this method is intended to be "package private" + * withing goog.html. DO NOT call SafeHtml.create... from outside this + * package; use appropriate wrappers instead. + */ +goog.html.uncheckedconversions.safeHtmlFromStringKnownToSatisfyTypeContract = + function(justification, html, opt_dir) { + // unwrap() called inside an assert so that justification can be optimized + // away in production code. + goog.asserts.assertString(goog.string.Const.unwrap(justification), + 'must provide justification'); + goog.asserts.assert( + !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)), + 'must provide non-empty justification'); + return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse( + html, opt_dir || null); +}; + + +/** + * Performs an "unchecked conversion" to SafeScript from a plain string that is + * known to satisfy the SafeScript type contract. + * + * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure + * that the value of {@code script} satisfies the SafeScript type contract in + * all possible program states. + * + * + * @param {!goog.string.Const} justification A constant string explaining why + * this use of this method is safe. May include a security review ticket + * number. + * @param {string} script The string to wrap as a SafeScript. + * @return {!goog.html.SafeScript} The value of {@code script}, wrapped in a + * SafeScript object. + */ +goog.html.uncheckedconversions.safeScriptFromStringKnownToSatisfyTypeContract = + function(justification, script) { + // unwrap() called inside an assert so that justification can be optimized + // away in production code. + goog.asserts.assertString(goog.string.Const.unwrap(justification), + 'must provide justification'); + goog.asserts.assert( + !goog.string.isEmpty(goog.string.Const.unwrap(justification)), + 'must provide non-empty justification'); + return goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse( + script); +}; + + +/** + * Performs an "unchecked conversion" to SafeStyle from a plain string that is + * known to satisfy the SafeStyle type contract. + * + * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure + * that the value of {@code style} satisfies the SafeUrl type contract in all + * possible program states. + * + * + * @param {!goog.string.Const} justification A constant string explaining why + * this use of this method is safe. May include a security review ticket + * number. + * @param {string} style The string to wrap as a SafeStyle. + * @return {!goog.html.SafeStyle} The value of {@code style}, wrapped in a + * SafeStyle object. + */ +goog.html.uncheckedconversions.safeStyleFromStringKnownToSatisfyTypeContract = + function(justification, style) { + // unwrap() called inside an assert so that justification can be optimized + // away in production code. + goog.asserts.assertString(goog.string.Const.unwrap(justification), + 'must provide justification'); + goog.asserts.assert( + !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)), + 'must provide non-empty justification'); + return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse( + style); +}; + + +/** + * Performs an "unchecked conversion" to SafeStyleSheet from a plain string + * that is known to satisfy the SafeStyleSheet type contract. + * + * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure + * that the value of {@code styleSheet} satisfies the SafeUrl type contract in + * all possible program states. + * + * + * @param {!goog.string.Const} justification A constant string explaining why + * this use of this method is safe. May include a security review ticket + * number. + * @param {string} styleSheet The string to wrap as a SafeStyleSheet. + * @return {!goog.html.SafeStyleSheet} The value of {@code styleSheet}, wrapped + * in a SafeStyleSheet object. + */ +goog.html.uncheckedconversions. + safeStyleSheetFromStringKnownToSatisfyTypeContract = + function(justification, styleSheet) { + // unwrap() called inside an assert so that justification can be optimized + // away in production code. + goog.asserts.assertString(goog.string.Const.unwrap(justification), + 'must provide justification'); + goog.asserts.assert( + !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)), + 'must provide non-empty justification'); + return goog.html.SafeStyleSheet. + createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(styleSheet); +}; + + +/** + * Performs an "unchecked conversion" to SafeUrl from a plain string that is + * known to satisfy the SafeUrl type contract. + * + * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure + * that the value of {@code url} satisfies the SafeUrl type contract in all + * possible program states. + * + * + * @param {!goog.string.Const} justification A constant string explaining why + * this use of this method is safe. May include a security review ticket + * number. + * @param {string} url The string to wrap as a SafeUrl. + * @return {!goog.html.SafeUrl} The value of {@code url}, wrapped in a SafeUrl + * object. + */ +goog.html.uncheckedconversions.safeUrlFromStringKnownToSatisfyTypeContract = + function(justification, url) { + // unwrap() called inside an assert so that justification can be optimized + // away in production code. + goog.asserts.assertString(goog.string.Const.unwrap(justification), + 'must provide justification'); + goog.asserts.assert( + !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)), + 'must provide non-empty justification'); + return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url); +}; + + +/** + * Performs an "unchecked conversion" to TrustedResourceUrl from a plain string + * that is known to satisfy the TrustedResourceUrl type contract. + * + * IMPORTANT: Uses of this method must be carefully security-reviewed to ensure + * that the value of {@code url} satisfies the TrustedResourceUrl type contract + * in all possible program states. + * + * + * @param {!goog.string.Const} justification A constant string explaining why + * this use of this method is safe. May include a security review ticket + * number. + * @param {string} url The string to wrap as a TrustedResourceUrl. + * @return {!goog.html.TrustedResourceUrl} The value of {@code url}, wrapped in + * a TrustedResourceUrl object. + */ +goog.html.uncheckedconversions. + trustedResourceUrlFromStringKnownToSatisfyTypeContract = + function(justification, url) { + // unwrap() called inside an assert so that justification can be optimized + // away in production code. + goog.asserts.assertString(goog.string.Const.unwrap(justification), + 'must provide justification'); + goog.asserts.assert( + !goog.string.isEmptyOrWhitespace(goog.string.Const.unwrap(justification)), + 'must provide non-empty justification'); + return goog.html.TrustedResourceUrl. + createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(url); +}; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/html/utils.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/html/utils.js b/externs/GCL/externs/goog/html/utils.js new file mode 100644 index 0000000..c54381b --- /dev/null +++ b/externs/GCL/externs/goog/html/utils.js @@ -0,0 +1,67 @@ +// Copyright 2013 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/** + * @fileoverview HTML processing utilities for HTML in string form. + */ + +goog.provide('goog.html.utils'); + +goog.require('goog.string'); + + +/** + * Extracts plain text from HTML. + * + * This behaves similarly to extracting textContent from a hypothetical DOM + * element containing the specified HTML. Block-level elements such as div are + * surrounded with whitespace, but inline elements are not. Span is treated as + * a block level element because it is often used as a container. Breaking + * spaces are compressed and trimmed. + * + * @param {string} value The input HTML to have tags removed. + * @return {string} The plain text of value without tags, HTML comments, or + * other non-text content. Does NOT return safe HTML! + */ +goog.html.utils.stripHtmlTags = function(value) { + // TODO(user): Make a version that extracts text attributes such as alt. + return goog.string.unescapeEntities(goog.string.trim(value.replace( + goog.html.utils.HTML_TAG_REGEX_, function(fullMatch, tagName) { + return goog.html.utils.INLINE_HTML_TAG_REGEX_.test(tagName) ? '' : ' '; + }). + replace(/[\t\n ]+/g, ' '))); +}; + + +/** + * Matches all tags that do not require extra space. + * + * @const + * @private {RegExp} + */ +goog.html.utils.INLINE_HTML_TAG_REGEX_ = + /^(?:abbr|acronym|address|b|em|i|small|strong|su[bp]|u)$/i; + + +/** + * Matches all tags, HTML comments, and DOCTYPEs in tag soup HTML. + * By removing these, and replacing any '<' or '>' characters with + * entities we guarantee that the result can be embedded into + * an attribute without introducing a tag boundary. + * + * @private {RegExp} + * @const + */ +goog.html.utils.HTML_TAG_REGEX_ = /<[!\/]?([a-z0-9]+)([\/ ][^>]*)?>/gi; http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/e2cad6e6/externs/GCL/externs/goog/i18n/bidi.js ---------------------------------------------------------------------- diff --git a/externs/GCL/externs/goog/i18n/bidi.js b/externs/GCL/externs/goog/i18n/bidi.js new file mode 100644 index 0000000..0f85cc2 --- /dev/null +++ b/externs/GCL/externs/goog/i18n/bidi.js @@ -0,0 +1,897 @@ +// Copyright 2007 The Closure Library Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS-IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @fileoverview Utility functions for supporting Bidi issues. + */ + + +/** + * Namespace for bidi supporting functions. + */ +goog.provide('goog.i18n.bidi'); +goog.provide('goog.i18n.bidi.Dir'); +goog.provide('goog.i18n.bidi.DirectionalString'); +goog.provide('goog.i18n.bidi.Format'); + + +/** + * @define {boolean} FORCE_RTL forces the {@link goog.i18n.bidi.IS_RTL} constant + * to say that the current locale is a RTL locale. This should only be used + * if you want to override the default behavior for deciding whether the + * current locale is RTL or not. + * + * {@see goog.i18n.bidi.IS_RTL} + */ +goog.define('goog.i18n.bidi.FORCE_RTL', false); + + +/** + * Constant that defines whether or not the current locale is a RTL locale. + * If {@link goog.i18n.bidi.FORCE_RTL} is not true, this constant will default + * to check that {@link goog.LOCALE} is one of a few major RTL locales. + * + *

This is designed to be a maximally efficient compile-time constant. For + * example, for the default goog.LOCALE, compiling + * "if (goog.i18n.bidi.IS_RTL) alert('rtl') else {}" should produce no code. It + * is this design consideration that limits the implementation to only + * supporting a few major RTL locales, as opposed to the broader repertoire of + * something like goog.i18n.bidi.isRtlLanguage. + * + *

Since this constant refers to the directionality of the locale, it is up + * to the caller to determine if this constant should also be used for the + * direction of the UI. + * + * {@see goog.LOCALE} + * + * @type {boolean} + * + * TODO(user): write a test that checks that this is a compile-time constant. + */ +goog.i18n.bidi.IS_RTL = goog.i18n.bidi.FORCE_RTL || + ( + (goog.LOCALE.substring(0, 2).toLowerCase() == 'ar' || + goog.LOCALE.substring(0, 2).toLowerCase() == 'fa' || + goog.LOCALE.substring(0, 2).toLowerCase() == 'he' || + goog.LOCALE.substring(0, 2).toLowerCase() == 'iw' || + goog.LOCALE.substring(0, 2).toLowerCase() == 'ps' || + goog.LOCALE.substring(0, 2).toLowerCase() == 'sd' || + goog.LOCALE.substring(0, 2).toLowerCase() == 'ug' || + goog.LOCALE.substring(0, 2).toLowerCase() == 'ur' || + goog.LOCALE.substring(0, 2).toLowerCase() == 'yi') && + (goog.LOCALE.length == 2 || + goog.LOCALE.substring(2, 3) == '-' || + goog.LOCALE.substring(2, 3) == '_') + ) || ( + goog.LOCALE.length >= 3 && + goog.LOCALE.substring(0, 3).toLowerCase() == 'ckb' && + (goog.LOCALE.length == 3 || + goog.LOCALE.substring(3, 4) == '-' || + goog.LOCALE.substring(3, 4) == '_') + ); + + +/** + * Unicode formatting characters and directionality string constants. + * @enum {string} + */ +goog.i18n.bidi.Format = { + /** Unicode "Left-To-Right Embedding" (LRE) character. */ + LRE: '\u202A', + /** Unicode "Right-To-Left Embedding" (RLE) character. */ + RLE: '\u202B', + /** Unicode "Pop Directional Formatting" (PDF) character. */ + PDF: '\u202C', + /** Unicode "Left-To-Right Mark" (LRM) character. */ + LRM: '\u200E', + /** Unicode "Right-To-Left Mark" (RLM) character. */ + RLM: '\u200F' +}; + + +/** + * Directionality enum. + * @enum {number} + */ +goog.i18n.bidi.Dir = { + /** + * Left-to-right. + */ + LTR: 1, + + /** + * Right-to-left. + */ + RTL: -1, + + /** + * Neither left-to-right nor right-to-left. + */ + NEUTRAL: 0 +}; + + +/** + * 'right' string constant. + * @type {string} + */ +goog.i18n.bidi.RIGHT = 'right'; + + +/** + * 'left' string constant. + * @type {string} + */ +goog.i18n.bidi.LEFT = 'left'; + + +/** + * 'left' if locale is RTL, 'right' if not. + * @type {string} + */ +goog.i18n.bidi.I18N_RIGHT = goog.i18n.bidi.IS_RTL ? goog.i18n.bidi.LEFT : + goog.i18n.bidi.RIGHT; + + +/** + * 'right' if locale is RTL, 'left' if not. + * @type {string} + */ +goog.i18n.bidi.I18N_LEFT = goog.i18n.bidi.IS_RTL ? goog.i18n.bidi.RIGHT : + goog.i18n.bidi.LEFT; + + +/** + * Convert a directionality given in various formats to a goog.i18n.bidi.Dir + * constant. Useful for interaction with different standards of directionality + * representation. + * + * @param {goog.i18n.bidi.Dir|number|boolean|null} givenDir Directionality given + * in one of the following formats: + * 1. A goog.i18n.bidi.Dir constant. + * 2. A number (positive = LTR, negative = RTL, 0 = neutral). + * 3. A boolean (true = RTL, false = LTR). + * 4. A null for unknown directionality. + * @param {boolean=} opt_noNeutral Whether a givenDir of zero or + * goog.i18n.bidi.Dir.NEUTRAL should be treated as null, i.e. unknown, in + * order to preserve legacy behavior. + * @return {?goog.i18n.bidi.Dir} A goog.i18n.bidi.Dir constant matching the + * given directionality. If given null, returns null (i.e. unknown). + */ +goog.i18n.bidi.toDir = function(givenDir, opt_noNeutral) { + if (typeof givenDir == 'number') { + // This includes the non-null goog.i18n.bidi.Dir case. + return givenDir > 0 ? goog.i18n.bidi.Dir.LTR : + givenDir < 0 ? goog.i18n.bidi.Dir.RTL : + opt_noNeutral ? null : goog.i18n.bidi.Dir.NEUTRAL; + } else if (givenDir == null) { + return null; + } else { + // Must be typeof givenDir == 'boolean'. + return givenDir ? goog.i18n.bidi.Dir.RTL : goog.i18n.bidi.Dir.LTR; + } +}; + + +/** + * A practical pattern to identify strong LTR characters. This pattern is not + * theoretically correct according to the Unicode standard. It is simplified for + * performance and small code size. + * @type {string} + * @private + */ +goog.i18n.bidi.ltrChars_ = + 'A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF' + + '\u200E\u2C00-\uFB1C\uFE00-\uFE6F\uFEFD-\uFFFF'; + + +/** + * A practical pattern to identify strong RTL character. This pattern is not + * theoretically correct according to the Unicode standard. It is simplified + * for performance and small code size. + * @type {string} + * @private + */ +goog.i18n.bidi.rtlChars_ = '\u0591-\u07FF\u200F\uFB1D-\uFDFF\uFE70-\uFEFC'; + + +/** + * Simplified regular expression for an HTML tag (opening or closing) or an HTML + * escape. We might want to skip over such expressions when estimating the text + * directionality. + * @type {RegExp} + * @private + */ +goog.i18n.bidi.htmlSkipReg_ = /<[^>]*>|&[^;]+;/g; + + +/** + * Returns the input text with spaces instead of HTML tags or HTML escapes, if + * opt_isStripNeeded is true. Else returns the input as is. + * Useful for text directionality estimation. + * Note: the function should not be used in other contexts; it is not 100% + * correct, but rather a good-enough implementation for directionality + * estimation purposes. + * @param {string} str The given string. + * @param {boolean=} opt_isStripNeeded Whether to perform the stripping. + * Default: false (to retain consistency with calling functions). + * @return {string} The given string cleaned of HTML tags / escapes. + * @private + */ +goog.i18n.bidi.stripHtmlIfNeeded_ = function(str, opt_isStripNeeded) { + return opt_isStripNeeded ? str.replace(goog.i18n.bidi.htmlSkipReg_, '') : + str; +}; + + +/** + * Regular expression to check for RTL characters. + * @type {RegExp} + * @private + */ +goog.i18n.bidi.rtlCharReg_ = new RegExp('[' + goog.i18n.bidi.rtlChars_ + ']'); + + +/** + * Regular expression to check for LTR characters. + * @type {RegExp} + * @private + */ +goog.i18n.bidi.ltrCharReg_ = new RegExp('[' + goog.i18n.bidi.ltrChars_ + ']'); + + +/** + * Test whether the given string has any RTL characters in it. + * @param {string} str The given string that need to be tested. + * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. + * Default: false. + * @return {boolean} Whether the string contains RTL characters. + */ +goog.i18n.bidi.hasAnyRtl = function(str, opt_isHtml) { + return goog.i18n.bidi.rtlCharReg_.test(goog.i18n.bidi.stripHtmlIfNeeded_( + str, opt_isHtml)); +}; + + +/** + * Test whether the given string has any RTL characters in it. + * @param {string} str The given string that need to be tested. + * @return {boolean} Whether the string contains RTL characters. + * @deprecated Use hasAnyRtl. + */ +goog.i18n.bidi.hasRtlChar = goog.i18n.bidi.hasAnyRtl; + + +/** + * Test whether the given string has any LTR characters in it. + * @param {string} str The given string that need to be tested. + * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. + * Default: false. + * @return {boolean} Whether the string contains LTR characters. + */ +goog.i18n.bidi.hasAnyLtr = function(str, opt_isHtml) { + return goog.i18n.bidi.ltrCharReg_.test(goog.i18n.bidi.stripHtmlIfNeeded_( + str, opt_isHtml)); +}; + + +/** + * Regular expression pattern to check if the first character in the string + * is LTR. + * @type {RegExp} + * @private + */ +goog.i18n.bidi.ltrRe_ = new RegExp('^[' + goog.i18n.bidi.ltrChars_ + ']'); + + +/** + * Regular expression pattern to check if the first character in the string + * is RTL. + * @type {RegExp} + * @private + */ +goog.i18n.bidi.rtlRe_ = new RegExp('^[' + goog.i18n.bidi.rtlChars_ + ']'); + + +/** + * Check if the first character in the string is RTL or not. + * @param {string} str The given string that need to be tested. + * @return {boolean} Whether the first character in str is an RTL char. + */ +goog.i18n.bidi.isRtlChar = function(str) { + return goog.i18n.bidi.rtlRe_.test(str); +}; + + +/** + * Check if the first character in the string is LTR or not. + * @param {string} str The given string that need to be tested. + * @return {boolean} Whether the first character in str is an LTR char. + */ +goog.i18n.bidi.isLtrChar = function(str) { + return goog.i18n.bidi.ltrRe_.test(str); +}; + + +/** + * Check if the first character in the string is neutral or not. + * @param {string} str The given string that need to be tested. + * @return {boolean} Whether the first character in str is a neutral char. + */ +goog.i18n.bidi.isNeutralChar = function(str) { + return !goog.i18n.bidi.isLtrChar(str) && !goog.i18n.bidi.isRtlChar(str); +}; + + +/** + * Regular expressions to check if a piece of text is of LTR directionality + * on first character with strong directionality. + * @type {RegExp} + * @private + */ +goog.i18n.bidi.ltrDirCheckRe_ = new RegExp( + '^[^' + goog.i18n.bidi.rtlChars_ + ']*[' + goog.i18n.bidi.ltrChars_ + ']'); + + +/** + * Regular expressions to check if a piece of text is of RTL directionality + * on first character with strong directionality. + * @type {RegExp} + * @private + */ +goog.i18n.bidi.rtlDirCheckRe_ = new RegExp( + '^[^' + goog.i18n.bidi.ltrChars_ + ']*[' + goog.i18n.bidi.rtlChars_ + ']'); + + +/** + * Check whether the first strongly directional character (if any) is RTL. + * @param {string} str String being checked. + * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. + * Default: false. + * @return {boolean} Whether RTL directionality is detected using the first + * strongly-directional character method. + */ +goog.i18n.bidi.startsWithRtl = function(str, opt_isHtml) { + return goog.i18n.bidi.rtlDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_( + str, opt_isHtml)); +}; + + +/** + * Check whether the first strongly directional character (if any) is RTL. + * @param {string} str String being checked. + * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. + * Default: false. + * @return {boolean} Whether RTL directionality is detected using the first + * strongly-directional character method. + * @deprecated Use startsWithRtl. + */ +goog.i18n.bidi.isRtlText = goog.i18n.bidi.startsWithRtl; + + +/** + * Check whether the first strongly directional character (if any) is LTR. + * @param {string} str String being checked. + * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. + * Default: false. + * @return {boolean} Whether LTR directionality is detected using the first + * strongly-directional character method. + */ +goog.i18n.bidi.startsWithLtr = function(str, opt_isHtml) { + return goog.i18n.bidi.ltrDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_( + str, opt_isHtml)); +}; + + +/** + * Check whether the first strongly directional character (if any) is LTR. + * @param {string} str String being checked. + * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. + * Default: false. + * @return {boolean} Whether LTR directionality is detected using the first + * strongly-directional character method. + * @deprecated Use startsWithLtr. + */ +goog.i18n.bidi.isLtrText = goog.i18n.bidi.startsWithLtr; + + +/** + * Regular expression to check if a string looks like something that must + * always be LTR even in RTL text, e.g. a URL. When estimating the + * directionality of text containing these, we treat these as weakly LTR, + * like numbers. + * @type {RegExp} + * @private + */ +goog.i18n.bidi.isRequiredLtrRe_ = /^http:\/\/.*/; + + +/** + * Check whether the input string either contains no strongly directional + * characters or looks like a url. + * @param {string} str String being checked. + * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. + * Default: false. + * @return {boolean} Whether neutral directionality is detected. + */ +goog.i18n.bidi.isNeutralText = function(str, opt_isHtml) { + str = goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml); + return goog.i18n.bidi.isRequiredLtrRe_.test(str) || + !goog.i18n.bidi.hasAnyLtr(str) && !goog.i18n.bidi.hasAnyRtl(str); +}; + + +/** + * Regular expressions to check if the last strongly-directional character in a + * piece of text is LTR. + * @type {RegExp} + * @private + */ +goog.i18n.bidi.ltrExitDirCheckRe_ = new RegExp( + '[' + goog.i18n.bidi.ltrChars_ + '][^' + goog.i18n.bidi.rtlChars_ + ']*$'); + + +/** + * Regular expressions to check if the last strongly-directional character in a + * piece of text is RTL. + * @type {RegExp} + * @private + */ +goog.i18n.bidi.rtlExitDirCheckRe_ = new RegExp( + '[' + goog.i18n.bidi.rtlChars_ + '][^' + goog.i18n.bidi.ltrChars_ + ']*$'); + + +/** + * Check if the exit directionality a piece of text is LTR, i.e. if the last + * strongly-directional character in the string is LTR. + * @param {string} str String being checked. + * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. + * Default: false. + * @return {boolean} Whether LTR exit directionality was detected. + */ +goog.i18n.bidi.endsWithLtr = function(str, opt_isHtml) { + return goog.i18n.bidi.ltrExitDirCheckRe_.test( + goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml)); +}; + + +/** + * Check if the exit directionality a piece of text is LTR, i.e. if the last + * strongly-directional character in the string is LTR. + * @param {string} str String being checked. + * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. + * Default: false. + * @return {boolean} Whether LTR exit directionality was detected. + * @deprecated Use endsWithLtr. + */ +goog.i18n.bidi.isLtrExitText = goog.i18n.bidi.endsWithLtr; + + +/** + * Check if the exit directionality a piece of text is RTL, i.e. if the last + * strongly-directional character in the string is RTL. + * @param {string} str String being checked. + * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. + * Default: false. + * @return {boolean} Whether RTL exit directionality was detected. + */ +goog.i18n.bidi.endsWithRtl = function(str, opt_isHtml) { + return goog.i18n.bidi.rtlExitDirCheckRe_.test( + goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml)); +}; + + +/** + * Check if the exit directionality a piece of text is RTL, i.e. if the last + * strongly-directional character in the string is RTL. + * @param {string} str String being checked. + * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. + * Default: false. + * @return {boolean} Whether RTL exit directionality was detected. + * @deprecated Use endsWithRtl. + */ +goog.i18n.bidi.isRtlExitText = goog.i18n.bidi.endsWithRtl; + + +/** + * A regular expression for matching right-to-left language codes. + * See {@link #isRtlLanguage} for the design. + * @type {RegExp} + * @private + */ +goog.i18n.bidi.rtlLocalesRe_ = new RegExp( + '^(ar|ckb|dv|he|iw|fa|nqo|ps|sd|ug|ur|yi|' + + '.*[-_](Arab|Hebr|Thaa|Nkoo|Tfng))' + + '(?!.*[-_](Latn|Cyrl)($|-|_))($|-|_)', + 'i'); + + +/** + * Check if a BCP 47 / III language code indicates an RTL language, i.e. either: + * - a language code explicitly specifying one of the right-to-left scripts, + * e.g. "az-Arab", or

+ * - a language code specifying one of the languages normally written in a + * right-to-left script, e.g. "fa" (Farsi), except ones explicitly specifying + * Latin or Cyrillic script (which are the usual LTR alternatives).

+ * The list of right-to-left scripts appears in the 100-199 range in + * http://www.unicode.org/iso15924/iso15924-num.html, of which Arabic and + * Hebrew are by far the most widely used. We also recognize Thaana, N'Ko, and + * Tifinagh, which also have significant modern usage. The rest (Syriac, + * Samaritan, Mandaic, etc.) seem to have extremely limited or no modern usage + * and are not recognized to save on code size. + * The languages usually written in a right-to-left script are taken as those + * with Suppress-Script: Hebr|Arab|Thaa|Nkoo|Tfng in + * http://www.iana.org/assignments/language-subtag-registry, + * as well as Central (or Sorani) Kurdish (ckb), Sindhi (sd) and Uyghur (ug). + * Other subtags of the language code, e.g. regions like EG (Egypt), are + * ignored. + * @param {string} lang BCP 47 (a.k.a III) language code. + * @return {boolean} Whether the language code is an RTL language. + */ +goog.i18n.bidi.isRtlLanguage = function(lang) { + return goog.i18n.bidi.rtlLocalesRe_.test(lang); +}; + + +/** + * Regular expression for bracket guard replacement in html. + * @type {RegExp} + * @private + */ +goog.i18n.bidi.bracketGuardHtmlRe_ = + /(\(.*?\)+)|(\[.*?\]+)|(\{.*?\}+)|(<.*?(>)+)/g; + + +/** + * Regular expression for bracket guard replacement in text. + * @type {RegExp} + * @private + */ +goog.i18n.bidi.bracketGuardTextRe_ = + /(\(.*?\)+)|(\[.*?\]+)|(\{.*?\}+)|(<.*?>+)/g; + + +/** + * Apply bracket guard using html span tag. This is to address the problem of + * messy bracket display frequently happens in RTL layout. + * @param {string} s The string that need to be processed. + * @param {boolean=} opt_isRtlContext specifies default direction (usually + * direction of the UI). + * @return {string} The processed string, with all bracket guarded. + */ +goog.i18n.bidi.guardBracketInHtml = function(s, opt_isRtlContext) { + var useRtl = opt_isRtlContext === undefined ? + goog.i18n.bidi.hasAnyRtl(s) : opt_isRtlContext; + if (useRtl) { + return s.replace(goog.i18n.bidi.bracketGuardHtmlRe_, + '$&'); + } + return s.replace(goog.i18n.bidi.bracketGuardHtmlRe_, + '$&'); +}; + + +/** + * Apply bracket guard using LRM and RLM. This is to address the problem of + * messy bracket display frequently happens in RTL layout. + * This version works for both plain text and html. But it does not work as + * good as guardBracketInHtml in some cases. + * @param {string} s The string that need to be processed. + * @param {boolean=} opt_isRtlContext specifies default direction (usually + * direction of the UI). + * @return {string} The processed string, with all bracket guarded. + */ +goog.i18n.bidi.guardBracketInText = function(s, opt_isRtlContext) { + var useRtl = opt_isRtlContext === undefined ? + goog.i18n.bidi.hasAnyRtl(s) : opt_isRtlContext; + var mark = useRtl ? goog.i18n.bidi.Format.RLM : goog.i18n.bidi.Format.LRM; + return s.replace(goog.i18n.bidi.bracketGuardTextRe_, mark + '$&' + mark); +}; + + +/** + * Enforce the html snippet in RTL directionality regardless overall context. + * If the html piece was enclosed by tag, dir will be applied to existing + * tag, otherwise a span tag will be added as wrapper. For this reason, if + * html snippet start with with tag, this tag must enclose the whole piece. If + * the tag already has a dir specified, this new one will override existing + * one in behavior (tested on FF and IE). + * @param {string} html The string that need to be processed. + * @return {string} The processed string, with directionality enforced to RTL. + */ +goog.i18n.bidi.enforceRtlInHtml = function(html) { + if (html.charAt(0) == '<') { + return html.replace(/<\w+/, '$& dir=rtl'); + } + // '\n' is important for FF so that it won't incorrectly merge span groups + return '\n' + html + ''; +}; + + +/** + * Enforce RTL on both end of the given text piece using unicode BiDi formatting + * characters RLE and PDF. + * @param {string} text The piece of text that need to be wrapped. + * @return {string} The wrapped string after process. + */ +goog.i18n.bidi.enforceRtlInText = function(text) { + return goog.i18n.bidi.Format.RLE + text + goog.i18n.bidi.Format.PDF; +}; + + +/** + * Enforce the html snippet in RTL directionality regardless overall context. + * If the html piece was enclosed by tag, dir will be applied to existing + * tag, otherwise a span tag will be added as wrapper. For this reason, if + * html snippet start with with tag, this tag must enclose the whole piece. If + * the tag already has a dir specified, this new one will override existing + * one in behavior (tested on FF and IE). + * @param {string} html The string that need to be processed. + * @return {string} The processed string, with directionality enforced to RTL. + */ +goog.i18n.bidi.enforceLtrInHtml = function(html) { + if (html.charAt(0) == '<') { + return html.replace(/<\w+/, '$& dir=ltr'); + } + // '\n' is important for FF so that it won't incorrectly merge span groups + return '\n' + html + ''; +}; + + +/** + * Enforce LTR on both end of the given text piece using unicode BiDi formatting + * characters LRE and PDF. + * @param {string} text The piece of text that need to be wrapped. + * @return {string} The wrapped string after process. + */ +goog.i18n.bidi.enforceLtrInText = function(text) { + return goog.i18n.bidi.Format.LRE + text + goog.i18n.bidi.Format.PDF; +}; + + +/** + * Regular expression to find dimensions such as "padding: .3 0.4ex 5px 6;" + * @type {RegExp} + * @private + */ +goog.i18n.bidi.dimensionsRe_ = + /:\s*([.\d][.\w]*)\s+([.\d][.\w]*)\s+([.\d][.\w]*)\s+([.\d][.\w]*)/g; + + +/** + * Regular expression for left. + * @type {RegExp} + * @private + */ +goog.i18n.bidi.leftRe_ = /left/gi; + + +/** + * Regular expression for right. + * @type {RegExp} + * @private + */ +goog.i18n.bidi.rightRe_ = /right/gi; + + +/** + * Placeholder regular expression for swapping. + * @type {RegExp} + * @private + */ +goog.i18n.bidi.tempRe_ = /%%%%/g; + + +/** + * Swap location parameters and 'left'/'right' in CSS specification. The + * processed string will be suited for RTL layout. Though this function can + * cover most cases, there are always exceptions. It is suggested to put + * those exceptions in separate group of CSS string. + * @param {string} cssStr CSS spefication string. + * @return {string} Processed CSS specification string. + */ +goog.i18n.bidi.mirrorCSS = function(cssStr) { + return cssStr. + // reverse dimensions + replace(goog.i18n.bidi.dimensionsRe_, ':$1 $4 $3 $2'). + replace(goog.i18n.bidi.leftRe_, '%%%%'). // swap left and right + replace(goog.i18n.bidi.rightRe_, goog.i18n.bidi.LEFT). + replace(goog.i18n.bidi.tempRe_, goog.i18n.bidi.RIGHT); +}; + + +/** + * Regular expression for hebrew double quote substitution, finding quote + * directly after hebrew characters. + * @type {RegExp} + * @private + */ +goog.i18n.bidi.doubleQuoteSubstituteRe_ = /([\u0591-\u05f2])"/g; + + +/** + * Regular expression for hebrew single quote substitution, finding quote + * directly after hebrew characters. + * @type {RegExp} + * @private + */ +goog.i18n.bidi.singleQuoteSubstituteRe_ = /([\u0591-\u05f2])'/g; + + +/** + * Replace the double and single quote directly after a Hebrew character with + * GERESH and GERSHAYIM. In such case, most likely that's user intention. + * @param {string} str String that need to be processed. + * @return {string} Processed string with double/single quote replaced. + */ +goog.i18n.bidi.normalizeHebrewQuote = function(str) { + return str. + replace(goog.i18n.bidi.doubleQuoteSubstituteRe_, '$1\u05f4'). + replace(goog.i18n.bidi.singleQuoteSubstituteRe_, '$1\u05f3'); +}; + + +/** + * Regular expression to split a string into "words" for directionality + * estimation based on relative word counts. + * @type {RegExp} + * @private + */ +goog.i18n.bidi.wordSeparatorRe_ = /\s+/; + + +/** + * Regular expression to check if a string contains any numerals. Used to + * differentiate between completely neutral strings and those containing + * numbers, which are weakly LTR. + * @type {RegExp} + * @private + */ +goog.i18n.bidi.hasNumeralsRe_ = /\d/; + + +/** + * This constant controls threshold of RTL directionality. + * @type {number} + * @private + */ +goog.i18n.bidi.rtlDetectionThreshold_ = 0.40; + + +/** + * Estimates the directionality of a string based on relative word counts. + * If the number of RTL words is above a certain percentage of the total number + * of strongly directional words, returns RTL. + * Otherwise, if any words are strongly or weakly LTR, returns LTR. + * Otherwise, returns UNKNOWN, which is used to mean "neutral". + * Numbers are counted as weakly LTR. + * @param {string} str The string to be checked. + * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. + * Default: false. + * @return {goog.i18n.bidi.Dir} Estimated overall directionality of {@code str}. + */ +goog.i18n.bidi.estimateDirection = function(str, opt_isHtml) { + var rtlCount = 0; + var totalCount = 0; + var hasWeaklyLtr = false; + var tokens = goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml). + split(goog.i18n.bidi.wordSeparatorRe_); + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + if (goog.i18n.bidi.startsWithRtl(token)) { + rtlCount++; + totalCount++; + } else if (goog.i18n.bidi.isRequiredLtrRe_.test(token)) { + hasWeaklyLtr = true; + } else if (goog.i18n.bidi.hasAnyLtr(token)) { + totalCount++; + } else if (goog.i18n.bidi.hasNumeralsRe_.test(token)) { + hasWeaklyLtr = true; + } + } + + return totalCount == 0 ? + (hasWeaklyLtr ? goog.i18n.bidi.Dir.LTR : goog.i18n.bidi.Dir.NEUTRAL) : + (rtlCount / totalCount > goog.i18n.bidi.rtlDetectionThreshold_ ? + goog.i18n.bidi.Dir.RTL : goog.i18n.bidi.Dir.LTR); +}; + + +/** + * Check the directionality of a piece of text, return true if the piece of + * text should be laid out in RTL direction. + * @param {string} str The piece of text that need to be detected. + * @param {boolean=} opt_isHtml Whether str is HTML / HTML-escaped. + * Default: false. + * @return {boolean} Whether this piece of text should be laid out in RTL. + */ +goog.i18n.bidi.detectRtlDirectionality = function(str, opt_isHtml) { + return goog.i18n.bidi.estimateDirection(str, opt_isHtml) == + goog.i18n.bidi.Dir.RTL; +}; + + +/** + * Sets text input element's directionality and text alignment based on a + * given directionality. Does nothing if the given directionality is unknown or + * neutral. + * @param {Element} element Input field element to set directionality to. + * @param {goog.i18n.bidi.Dir|number|boolean|null} dir Desired directionality, + * given in one of the following formats: + * 1. A goog.i18n.bidi.Dir constant. + * 2. A number (positive = LRT, negative = RTL, 0 = neutral). + * 3. A boolean (true = RTL, false = LTR). + * 4. A null for unknown directionality. + */ +goog.i18n.bidi.setElementDirAndAlign = function(element, dir) { + if (element) { + dir = goog.i18n.bidi.toDir(dir); + if (dir) { + element.style.textAlign = + dir == goog.i18n.bidi.Dir.RTL ? + goog.i18n.bidi.RIGHT : goog.i18n.bidi.LEFT; + element.dir = dir == goog.i18n.bidi.Dir.RTL ? 'rtl' : 'ltr'; + } + } +}; + + +/** + * Sets element dir based on estimated directionality of the given text. + * @param {!Element} element + * @param {string} text + */ +goog.i18n.bidi.setElementDirByTextDirectionality = function(element, text) { + switch (goog.i18n.bidi.estimateDirection(text)) { + case (goog.i18n.bidi.Dir.LTR): + element.dir = 'ltr'; + break; + case (goog.i18n.bidi.Dir.RTL): + element.dir = 'rtl'; + break; + default: + // Default for no direction, inherit from document. + element.removeAttribute('dir'); + } +}; + + + +/** + * Strings that have an (optional) known direction. + * + * Implementations of this interface are string-like objects that carry an + * attached direction, if known. + * @interface + */ +goog.i18n.bidi.DirectionalString = function() {}; + + +/** + * Interface marker of the DirectionalString interface. + * + * This property can be used to determine at runtime whether or not an object + * implements this interface. All implementations of this interface set this + * property to {@code true}. + * @type {boolean} + */ +goog.i18n.bidi.DirectionalString.prototype. + implementsGoogI18nBidiDirectionalString; + + +/** + * Retrieves this object's known direction (if any). + * @return {?goog.i18n.bidi.Dir} The known direction. Null if unknown. + */ +goog.i18n.bidi.DirectionalString.prototype.getDirection;