[FEATURE] Add integrity property to JavaScript files 32/39132/2
authorXavier Perseguers <xavier@typo3.org>
Fri, 1 May 2015 07:43:23 +0000 (09:43 +0200)
committerFrank Nägler <typo3@naegler.net>
Fri, 1 May 2015 12:38:22 +0000 (14:38 +0200)
Add a property 'integrity="some-hash"' to JavaScript files via TypoScript
page.includeJSlibs.<array>.integrity = some-hash

This patch affects the TypoScript PAGE properties
* includeJSlibs
* includeJSFooterlibs
* includeJS
* includeJSFooter

Resolves: #66698
Releases: master
Change-Id: I82b6aaaf424d7056844912f7194f88e01a972ec3
Reviewed-on: http://review.typo3.org/39132
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Reviewed-by: Frank Nägler <typo3@naegler.net>
Tested-by: Frank Nägler <typo3@naegler.net>
typo3/sysext/core/Classes/Page/PageRenderer.php
typo3/sysext/core/Documentation/Changelog/master/Feature-66698-AddIntegrityPropertyToJavaScriptFiles.rst [new file with mode: 0644]
typo3/sysext/frontend/Classes/Page/PageGenerator.php

index 865c0b3..d988d2a 100644 (file)
@@ -1155,9 +1155,10 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface {
         * @param bool $excludeFromConcatenation
         * @param string $splitChar The char used to split the allWrap value, default is "|"
         * @param bool $async Flag if property 'async="async"' should be added to JavaScript tags
+        * @param string $integrity Subresource Integrity (SRI)
         * @return void
         */
-       public function addJsLibrary($name, $file, $type = 'text/javascript', $compress = FALSE, $forceOnTop = FALSE, $allWrap = '', $excludeFromConcatenation = FALSE, $splitChar = '|', $async = FALSE) {
+       public function addJsLibrary($name, $file, $type = 'text/javascript', $compress = FALSE, $forceOnTop = FALSE, $allWrap = '', $excludeFromConcatenation = FALSE, $splitChar = '|', $async = FALSE, $integrity = '') {
                if (!$type) {
                        $type = 'text/javascript';
                }
@@ -1171,7 +1172,8 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface {
                                'allWrap' => $allWrap,
                                'excludeFromConcatenation' => $excludeFromConcatenation,
                                'splitChar' => $splitChar,
-                               'async' => $async
+                               'async' => $async,
+                               'integrity' => $integrity,
                        );
                }
        }
@@ -1188,9 +1190,10 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface {
         * @param bool $excludeFromConcatenation
         * @param string $splitChar The char used to split the allWrap value, default is "|"
         * @param bool $async Flag if property 'async="async"' should be added to JavaScript tags
+        * @param string $integrity Subresource Integrity (SRI)
         * @return void
         */
-       public function addJsFooterLibrary($name, $file, $type = 'text/javascript', $compress = FALSE, $forceOnTop = FALSE, $allWrap = '', $excludeFromConcatenation = FALSE, $splitChar = '|', $async = FALSE) {
+       public function addJsFooterLibrary($name, $file, $type = 'text/javascript', $compress = FALSE, $forceOnTop = FALSE, $allWrap = '', $excludeFromConcatenation = FALSE, $splitChar = '|', $async = FALSE, $integrity = '') {
                if (!$type) {
                        $type = 'text/javascript';
                }
@@ -1204,7 +1207,8 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface {
                                'allWrap' => $allWrap,
                                'excludeFromConcatenation' => $excludeFromConcatenation,
                                'splitChar' => $splitChar,
-                               'async' => $async
+                               'async' => $async,
+                               'integrity' => $integrity,
                        );
                }
        }
@@ -1220,9 +1224,10 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface {
         * @param bool $excludeFromConcatenation
         * @param string $splitChar The char used to split the allWrap value, default is "|"
         * @param bool $async Flag if property 'async="async"' should be added to JavaScript tags
+        * @param string $integrity Subresource Integrity (SRI)
         * @return void
         */
-       public function addJsFile($file, $type = 'text/javascript', $compress = TRUE, $forceOnTop = FALSE, $allWrap = '', $excludeFromConcatenation = FALSE, $splitChar = '|', $async = FALSE) {
+       public function addJsFile($file, $type = 'text/javascript', $compress = TRUE, $forceOnTop = FALSE, $allWrap = '', $excludeFromConcatenation = FALSE, $splitChar = '|', $async = FALSE, $integrity = '') {
                if (!$type) {
                        $type = 'text/javascript';
                }
@@ -1239,7 +1244,8 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface {
                                'allWrap' => $allWrap,
                                'excludeFromConcatenation' => $excludeFromConcatenation,
                                'splitChar' => $splitChar,
-                               'async' => $async
+                               'async' => $async,
+                               'integrity' => $integrity,
                        );
                }
        }
@@ -1255,9 +1261,10 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface {
         * @param bool $excludeFromConcatenation
         * @param string $splitChar The char used to split the allWrap value, default is "|"
         * @param bool $async Flag if property 'async="async"' should be added to JavaScript tags
+        * @param string $integrity Subresource Integrity (SRI)
         * @return void
         */
-       public function addJsFooterFile($file, $type = 'text/javascript', $compress = TRUE, $forceOnTop = FALSE, $allWrap = '', $excludeFromConcatenation = FALSE, $splitChar = '|', $async = FALSE) {
+       public function addJsFooterFile($file, $type = 'text/javascript', $compress = TRUE, $forceOnTop = FALSE, $allWrap = '', $excludeFromConcatenation = FALSE, $splitChar = '|', $async = FALSE, $integrity = '') {
                if (!$type) {
                        $type = 'text/javascript';
                }
@@ -1274,7 +1281,8 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface {
                                'allWrap' => $allWrap,
                                'excludeFromConcatenation' => $excludeFromConcatenation,
                                'splitChar' => $splitChar,
-                               'async' => $async
+                               'async' => $async,
+                               'integrity' => $integrity,
                        );
                }
        }
@@ -2421,7 +2429,8 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface {
                                $properties['file'] = GeneralUtility::resolveBackPath($properties['file']);
                                $properties['file'] = GeneralUtility::createVersionNumberedFilename($properties['file']);
                                $async = ($properties['async']) ? ' async="async"' : '';
-                               $tag = '<script src="' . htmlspecialchars($properties['file']) . '" type="' . htmlspecialchars($properties['type']) . '"' . $async . '></script>';
+                               $integrity = ($properties['integrity']) ? ' integrity="' . htmlspecialchars($properties['integrity']) . '"' : '';
+                               $tag = '<script src="' . htmlspecialchars($properties['file']) . '" type="' . htmlspecialchars($properties['type']) . '"' . $async . $integrity . '></script>';
                                if ($properties['allWrap']) {
                                        $wrapArr = explode($properties['splitChar'] ?: '|', $properties['allWrap'], 2);
                                        $tag = $wrapArr[0] . $tag . $wrapArr[1];
@@ -2462,7 +2471,8 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface {
                                $file = GeneralUtility::resolveBackPath($file);
                                $file = GeneralUtility::createVersionNumberedFilename($file);
                                $async = ($properties['async']) ? ' async="async"' : '';
-                               $tag = '<script src="' . htmlspecialchars($file) . '" type="' . htmlspecialchars($properties['type']) . '"' . $async . '></script>';
+                               $integrity = ($properties['integrity']) ? ' integrity="' . htmlspecialchars($properties['integrity']) . '"' : '';
+                               $tag = '<script src="' . htmlspecialchars($file) . '" type="' . htmlspecialchars($properties['type']) . '"' . $async . $integrity . '></script>';
                                if ($properties['allWrap']) {
                                        $wrapArr = explode($properties['splitChar'] ?: '|', $properties['allWrap'], 2);
                                        $tag = $wrapArr[0] . $tag . $wrapArr[1];
diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-66698-AddIntegrityPropertyToJavaScriptFiles.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-66698-AddIntegrityPropertyToJavaScriptFiles.rst
new file mode 100644 (file)
index 0000000..c834482
--- /dev/null
@@ -0,0 +1,38 @@
+============================================================
+Feature: #66698 - Add integrity property to JavaScript files
+============================================================
+
+Description
+===========
+
+Add a property ``integrity="some-hash"`` to JavaScript files via TypoScript
+
+``page.includeJSlibs.<array>.integrity = some-hash``
+
+This patch affects the TypoScript PAGE properties
+
+* includeJSLibs
+* includeJSFooterlibs
+* includeJS
+* includeJSFooter
+
+Usage:
+------
+
+.. code-block:: typoscript
+       :emphasize-lines: 6
+
+       page {
+               includeJS {
+                       jQuery = fileadmin/jquery-1.10.2.min.js
+                       jQuery.disableCompression = 1
+                       jQuery.excludeFromConcatenation = 1
+                       jQuery.integrity = sha256-C6CB9UYIS9UJeqinPHWTHVqh/E1uhG5Twh+Y5qFQmYg=
+               }
+       }
+
+..
+
+
+.. hint::
+       Integrity hashes may be generated using https://srihash.org/.
index 82e9b12..2ede73b 100644 (file)
@@ -684,7 +684,8 @@ class PageGenerator {
                                                        $jsFileConfig['allWrap'],
                                                        $jsFileConfig['excludeFromConcatenation'] ? TRUE : FALSE,
                                                        $jsFileConfig['allWrap.']['splitChar'],
-                                                       $jsFileConfig['async'] ? TRUE : FALSE
+                                                       $jsFileConfig['async'] ? TRUE : FALSE,
+                                                       $jsFileConfig['integrity']
                                                );
                                                unset($jsFileConfig);
                                        }
@@ -713,7 +714,8 @@ class PageGenerator {
                                                        $jsFileConfig['allWrap'],
                                                        $jsFileConfig['excludeFromConcatenation'] ? TRUE : FALSE,
                                                        $jsFileConfig['allWrap.']['splitChar'],
-                                                       $jsFileConfig['async'] ? TRUE : FALSE
+                                                       $jsFileConfig['async'] ? TRUE : FALSE,
+                                                       $jsFileConfig['integrity']
                                                );
                                                unset($jsFileConfig);
                                        }
@@ -742,7 +744,8 @@ class PageGenerator {
                                                        $jsConfig['allWrap'],
                                                        $jsConfig['excludeFromConcatenation'] ? TRUE : FALSE,
                                                        $jsConfig['allWrap.']['splitChar'],
-                                                       $jsConfig['async'] ? TRUE : FALSE
+                                                       $jsConfig['async'] ? TRUE : FALSE,
+                                                       $jsConfig['integrity']
                                                );
                                                unset($jsConfig);
                                        }
@@ -770,7 +773,8 @@ class PageGenerator {
                                                        $jsConfig['allWrap'],
                                                        $jsConfig['excludeFromConcatenation'] ? TRUE : FALSE,
                                                        $jsConfig['allWrap.']['splitChar'],
-                                                       $jsConfig['async'] ? TRUE : FALSE
+                                                       $jsConfig['async'] ? TRUE : FALSE,
+                                                       $jsConfig['integrity']
                                                );
                                                unset($jsConfig);
                                        }