0001    // The MIT License
0002    //
0003    // Copyright (c) 2015 Gwendal Roué
0004    //
0005    // Permission is hereby granted, free of charge, to any person obtaining a copy
0006    // of this software and associated documentation files (the "Software"), to deal
0007    // in the Software without restriction, including without limitation the rights
0008    // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
0009    // copies of the Software, and to permit persons to whom the Software is
0010    // furnished to do so, subject to the following conditions:
0011    //
0012    // The above copyright notice and this permission notice shall be included in
0013    // all copies or substantial portions of the Software.
0014    //
0015    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0016    // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0017    // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
0018    // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0019    // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
0020    // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
0021    // THE SOFTWARE.
0022    
0023    final class JavascriptEscapeHelper
JavascriptEscapeHelper.swift:41
        return Rendering(JavascriptEscapeHelper.escapeJavascript(rendering.string), rendering.contentType)
StandardLibrary.swift:117
    public static let javascriptEscape: MustacheBoxable = JavascriptEscapeHelper()
: MustacheBoxable { 0024 0025 var mustacheBox: MustacheBox { 0026 // Return a multi-facetted box, because JavascriptEscape interacts in 0027 // various ways with Mustache rendering. 0028 return MustacheBox( 0029 // It has a value: 0030 value: self, 0031 0032 // JavascriptEscape can be used as a filter: {{ javascriptEscape(x) }}: 0033 filter: Filter(filter), 0034 0035 // JavascriptEscape escapes all variable tags: {{# javascriptEscape }}...{{ x }}...{{/ javascriptEscape }} 0036 willRender: willRender) 0037 } 0038 0039 // This function is used for evaluating `javascriptEscape(x)` expressions. 0040 private func filter
JavascriptEscapeHelper.swift:33
            filter: Filter(filter),
JavascriptEscapeHelper.swift:56
                return try self.filter(rendering)
(rendering: Rendering) throws -> Rendering { 0041 return Rendering(JavascriptEscapeHelper.escapeJavascript(rendering.string), rendering.contentType) 0042 } 0043 0044 // A WillRenderFunction: this function lets JavascriptEscape change values that 0045 // are about to be rendered to their escaped counterpart. 0046 // 0047 // It is activated as soon as the formatter enters the context stack, when 0048 // used in a section {{# javascriptEscape }}...{{/ javascriptEscape }}. 0049 private func willRender
JavascriptEscapeHelper.swift:36
            willRender: willRender)
(tag: Tag, box: MustacheBox) -> MustacheBox { 0050 switch tag.type { 0051 case .Variable: 0052 // We don't know if the box contains a String, so let's escape its 0053 // rendering. 0054 return Box(render: { (info: RenderingInfo) -> Rendering in 0055 let rendering = try box.render(info: info) 0056 return try self.filter(rendering) 0057 }) 0058 case .Section: 0059 return box 0060 } 0061 } 0062 0063 private class func escapeJavascript
JavascriptEscapeHelper.swift:41
        return Rendering(JavascriptEscapeHelper.escapeJavascript(rendering.string), rendering.contentType)
(string: String) -> String { 0064 // This table comes from https://github.com/django/django/commit/8c4a525871df19163d5bfdf5939eff33b544c2e2#django/template/defaultfilters.py 0065 // 0066 // Quoting Malcolm Tredinnick: 0067 // > Added extra robustness to the escapejs filter so that all invalid 0068 // > characters are correctly escaped. This avoids any chance to inject 0069 // > raw HTML inside <script> tags. Thanks to Mike Wiacek for the patch 0070 // > and Collin Grady for the tests. 0071 // 0072 // Quoting Mike Wiacek from https://code.djangoproject.com/ticket/7177 0073 // > The escapejs filter currently escapes a small subset of characters 0074 // > to prevent JavaScript injection. However, the resulting strings can 0075 // > still contain valid HTML, leading to XSS vulnerabilities. Using hex 0076 // > encoding as opposed to backslash escaping, effectively prevents 0077 // > Javascript injection and also helps prevent XSS. Attached is a 0078 // > small patch that modifies the _js_escapes tuple to use hex encoding 0079 // > on an expanded set of characters. 0080 // 0081 // The initial django commit used `\xNN` syntax. The \u syntax was 0082 // introduced later for JSON compatibility. 0083 0084 let escapeTable: [Character: String] = [ 0085 "\0": "\\u0000", 0086 "\u{01}": "\\u0001", 0087 "\u{02}": "\\u0002", 0088 "\u{03}": "\\u0003", 0089 "\u{04}": "\\u0004", 0090 "\u{05}": "\\u0005", 0091 "\u{06}": "\\u0006", 0092 "\u{07}": "\\u0007", 0093 "\u{08}": "\\u0008", 0094 "\u{09}": "\\u0009", 0095 "\u{0A}": "\\u000A", 0096 "\u{0B}": "\\u000B", 0097 "\u{0C}": "\\u000C", 0098 "\u{0D}": "\\u000D", 0099 "\u{0E}": "\\u000E", 0100 "\u{0F}": "\\u000F", 0101 "\u{10}": "\\u0010", 0102 "\u{11}": "\\u0011", 0103 "\u{12}": "\\u0012", 0104 "\u{13}": "\\u0013", 0105 "\u{14}": "\\u0014", 0106 "\u{15}": "\\u0015", 0107 "\u{16}": "\\u0016", 0108 "\u{17}": "\\u0017", 0109 "\u{18}": "\\u0018", 0110 "\u{19}": "\\u0019", 0111 "\u{1A}": "\\u001A", 0112 "\u{1B}": "\\u001B", 0113 "\u{1C}": "\\u001C", 0114 "\u{1D}": "\\u001D", 0115 "\u{1E}": "\\u001E", 0116 "\u{1F}": "\\u001F", 0117 "\\": "\\u005C", 0118 "'": "\\u0027", 0119 "\"": "\\u0022", 0120 ">": "\\u003E", 0121 "<": "\\u003C", 0122 "&": "\\u0026", 0123 "=": "\\u003D", 0124 "-": "\\u002D", 0125 ";": "\\u003B", 0126 "\u{2028}": "\\u2028", 0127 "\u{2029}": "\\u2029", 0128 // Required to pass GRMustache suite test "`javascript.escape` escapes control characters" 0129 "\r\n": "\\u000D\\u000A", 0130 ] 0131 var escaped = "" 0132 for c in string.characters { 0133 if let escapedString = escapeTable[c] { 0134 escaped += escapedString 0135 } else { 0136 escaped.append(c) 0137 } 0138 } 0139 return escaped 0140 } 0141 } 0142