3636import goc .webtemplate .component .jsonentities .AppFooter ;
3737import goc .webtemplate .component .jsonentities .AppTop ;
3838import goc .webtemplate .component .jsonentities .CDTSEnvironment ;
39+ import goc .webtemplate .component .jsonentities .CDTSEnvironmentList ;
3940import goc .webtemplate .component .jsonentities .FeedbackLink ;
4041import goc .webtemplate .component .jsonentities .Footer ;
4142import goc .webtemplate .component .jsonentities .IPreFooter ;
6263 */
6364public abstract class AbstractCoreBean {
6465 /**
65- * Hold the table of CDTS environment configuration objects (loaded the first time it is accessed).
66+ * Holds the table of CDTS environment configuration objects (loaded the first time it is accessed).
6667 */
6768 private static HashMap <String , CDTSEnvironment > cdtsEnvironments = null ;
69+ /**
70+ * Holds the table of theme/version -> fileName -> SRIHash
71+ */
72+ private static HashMap <String , HashMap <String , String >> cdtsSRIHashes = null ;
6873
6974 /**
7075 * SimpleDateFormat object used to format dateModified-type dates.
@@ -91,7 +96,8 @@ private enum Themes { GCWEB, GCINTRANET }
9196 private String templateVersion = null ; // initialized in getTemplateVersion
9297 private String theme = null ; // initialized in getTheme
9398 private String subTheme = null ; // initialized in getSubTheme
94- private boolean useHttps = Boolean .parseBoolean (this .getResourceBundleString ("cdn" , "webtemplate_usehttps" ));
99+ private boolean useHttps = !"false" .equals (this .getResourceBundleString ("cdn" , "webtemplate_usehttps" )); //defaults to true if not specified/is not exactly "false"
100+ private boolean useSRI = !"false" .equals (this .getResourceBundleString ("cdn" , "webtemplate_usesri" )); //defaults to true if not specified/is not exactly "false"
95101 private boolean loadjQueryFromGoogle = Boolean .parseBoolean (this .getResourceBundleString ("cdn" , "wettemplate_loadjqueryfromgoogle" ));
96102 private String cdnLocalPath = null ; //initialized in getLocalPath
97103 private String headerTitle = "" ;
@@ -153,6 +159,7 @@ private enum Themes { GCWEB, GCINTRANET }
153159 //-------------------------------------------------------
154160 private String partialCDNPath = null ;
155161 private CDTSEnvironment currentCDTSEnvironment = null ;
162+ private HashMap <String , String > currentSRIHashes = null ;
156163 //-------------------------------------------------------
157164
158165 //-------------------------------------------------------
@@ -182,44 +189,65 @@ private static CDTSEnvironment getCDTSEnvironmentByName(String name) {
182189 return cdtsEnvironments .get (name );
183190 }
184191
192+ /**
193+ * Returns the table of fileName -> SRIHash for the specified theme and version.
194+ * @param theme Name of the theme, must be lowercase
195+ * @param version Version "name" (e.g. v9_9_9)
196+ */
197+ private static HashMap <String , String > getCDTSSRIHashes (String theme , String version ) {
198+ if (cdtsSRIHashes == null ) loadCDTSEnvironments ();
199+ return cdtsSRIHashes .get (theme + "/" + version );
200+ }
201+
185202 /**
186203 * Load environment json file (converts all environment names to lowercase)
187204 */
188205 private static synchronized void loadCDTSEnvironments () { //note the "static synchronized"... i.e. synchronized on AbstractCoreBean.class
189- HashMap <String , CDTSEnvironment > map = new HashMap <String , CDTSEnvironment >();
190- CDTSEnvironment .CDTSEnvironmentList tmpList ;
191- java .io .InputStream is = null ;
206+ HashMap <String , CDTSEnvironment > map = new HashMap <String , CDTSEnvironment >();
207+ HashMap <String , HashMap <String , String >> hashes = new HashMap <String , HashMap <String , String >>();
208+ CDTSEnvironmentList tmpList ;
209+ java .io .InputStream is = null ;
192210
193211 try {
194212 is = AbstractCoreBean .class .getResourceAsStream ("/goc/webtemplate/global/config/CDTSEnvironments.json" );
195213 if (is == null ) {
196214 System .err .println ("ERROR: CDTSEnvironment.json could not be read. Environment list will be empty. (/goc/webtemplate/global/config/CDTSEnvironments.json not found in jar)" );
197215 cdtsEnvironments = map ;
216+ cdtsSRIHashes = hashes ;
198217 return ;
199218 }
200219
201- tmpList = gson .fromJson (new java .io .InputStreamReader (is , "UTF-8" ), CDTSEnvironment . CDTSEnvironmentList .class );
220+ tmpList = gson .fromJson (new java .io .InputStreamReader (is , "UTF-8" ), CDTSEnvironmentList .class );
202221 for (CDTSEnvironment cdtsenv : tmpList .getEnvironments ()) {
203222 //(convert name to all lower-case)
204223 map .put (cdtsenv .getName ().toLowerCase (), cdtsenv );
205224 }
225+ hashes = tmpList .getThemeSRIHashes ();
206226 }
207227 catch (Exception ex ) {
208228 System .err .println ("ERROR: CDTSEnvironment.json could not be read. Environment list will be empty. Exception: " + ex );
209- cdtsEnvironments = map ;
210229 }
211230 finally {
212231 try {is .close ();} catch (Throwable e ) {}
213232 }
214233
215234 cdtsEnvironments = map ;
235+ cdtsSRIHashes = hashes ;
216236 }
217237
218238 private CDTSEnvironment getCurrentCDTSEnvironment () {
219239 if (this .currentCDTSEnvironment == null ) this .currentCDTSEnvironment = getCDTSEnvironmentByName (this .getCDNEnvironment ().toLowerCase ());
220240 return this .currentCDTSEnvironment ;
221241 }
222242
243+ private HashMap <String , String > getCurrentCDTSSRIHashes () {
244+ if (this .currentSRIHashes == null ) {
245+ HashMap <String , String > sriMap = getCDTSSRIHashes (this .getTheme (), this .getTemplateVersion ());
246+ this .currentSRIHashes = sriMap != null ? sriMap : new HashMap <String , String >(); // if not found, initialize to empty map
247+ }
248+ return this .currentSRIHashes ;
249+ }
250+
223251 private void initializeOnce () {
224252 if (!this .initialized ) {
225253 this .initialized = true ; //do it BEFORE calling onWebTemplateInitialize to avoid endless loops
@@ -312,7 +340,7 @@ public void setFooterPath(String footerPath) {
312340
313341 templateVersion = this .getTemplateVersion ();
314342 envRun = "" ;
315- if (Utility .isNullOrEmpty (templateVersion )) {
343+ if (Utility .isNullOrEmpty (templateVersion ) || templateVersion . equals ( "rn" ) ) {
316344 if ((environment != null ) && environment .isVersionRnCombined ()) {
317345 templateVersion = "rn/" ;
318346 //(envRun stays blank)
@@ -354,8 +382,9 @@ public String getCDNEnvironment() {
354382 public void setCDNEnvironment (String value ) {
355383 this .cdnEnvironment = value ;
356384
357- //---[ The environment anme changed, we have a few cached values to clear so they are re-loaded from the proper environment
385+ //---[ The environment name changed, we have a few cached values to clear so they are re-loaded from the proper environment
358386 this .currentCDTSEnvironment = null ;
387+ this .currentSRIHashes = null ;
359388 this .cdtsCdnEnv = null ;
360389 this .partialCDNPath = null ;
361390 this .cdnLocalPath = null ;
@@ -452,6 +481,27 @@ public void setUseHttps(boolean value) {
452481 this .useHttps = value ;
453482 }
454483
484+ /**
485+ * Returns whether or not to include Sub Resource Integrity when inserting CDTS scripts and css.
486+ *
487+ * Set at application level via "webtemplate_usesri" property in cdn.properties,
488+ * can be overriden programatically.
489+ */
490+ public boolean getUseSRI () {
491+ this .initializeOnce ();
492+ return this .useSRI ;
493+ }
494+
495+ /**
496+ * Sets whether or not to include Sub Resource Integrity when inserting CDTS scripts and css.
497+ *
498+ * Set at application level via "webtemplate_usesri" property in cdn.properties,
499+ * can be overriden programatically.
500+ */
501+ public void setUseSRI (boolean value ) {
502+ this .useSRI = value ;
503+ }
504+
455505 /**
456506 * Returns the version of the CDN files to use to build the page. (e.g v4_0_47)
457507 *
@@ -481,6 +531,7 @@ public String getTemplateVersion() {
481531 */
482532 public void setTemplateVersion (String value ) {
483533 this .templateVersion = value ;
534+ this .currentSRIHashes = null ;
484535 }
485536
486537 /**
@@ -518,6 +569,7 @@ public String getTheme() {
518569 */
519570 public void setTheme (String value ) {
520571 this .theme = value ;
572+ this .currentSRIHashes = null ;
521573 }
522574
523575 /**
@@ -1495,7 +1547,7 @@ public boolean getHideCorporateFooter() {
14951547 public void setHideCorporateFooter (boolean value ) {
14961548 this .hideCorporateFooter = value ;
14971549 }
1498-
1550+
14991551 /**
15001552 * Returns whether to display a header menu on top of the page
15011553 *
@@ -1578,57 +1630,81 @@ public String getWebTemplateDistributionVersion() {
15781630 return Constants .WEB_TEMPLATE_DISTRIBUTION_VERSION ;
15791631 }
15801632
1633+ private String getPathAttributes (String pathAttributeName , String fileName ) {
1634+ StringBuilder buf = new StringBuilder (384 );
1635+
1636+ buf .append (pathAttributeName );
1637+ buf .append ("=\" " );
1638+ buf .append (this .getPartialCDNPath ());
1639+ buf .append (fileName );
1640+ buf .append ("\" " );
1641+ if (this .getUseSRI ()) {
1642+ HashMap <String , String > sriHashes = this .getCurrentCDTSSRIHashes ();
1643+
1644+ String hash = sriHashes .get (fileName );
1645+ if (hash != null ) { //if not found, simply don't issue SRI attributes
1646+ buf .append (" integrity=\" " );
1647+ buf .append (hash );
1648+ buf .append ("\" crossorigin=\" anonymous\" " );
1649+ }
1650+ }
1651+
1652+ return buf .toString ();
1653+ }
1654+
15811655 /**
1582- * Return the CDN path to the cdts-[subtheme]-styles.css file.
1656+ * Return the href/integrity/crossorigin attribute to the cdts-[subtheme]-styles.css file.
15831657 *
15841658 * (Used by template files when rendering)
15851659 */
1586- public String getCssPath () {
1660+ public String getCssPathAttributes () {
1661+ //---[ Figure out CSS file name
1662+ String fileName = "cdts-styles.css" ;
1663+
15871664 if (!this .isThemeGcWeb ()) {
15881665 //NOT gcweb...
15891666 String subTheme = this .getSubTheme ();
15901667 if (!Utility .isNullOrEmpty (subTheme )) {
15911668 subTheme = subTheme .toLowerCase ();
1592- //...limit to supported subthemes
1669+ //...limit to supported subthemes
15931670 if (subTheme .equals ("esdc" ) || subTheme .equals ("eccc" )) {
1594- return String .format ("%scdts -%s-styles.css" , this . getPartialCDNPath () , subTheme );
1671+ fileName = String .format ("cdts -%s-styles.css" , subTheme );
15951672 }
15961673 }
1597- }
1674+ } // (else we're gcweb or gcintranet with no subtheme value)
15981675
1599- //(if we get here, we're gcweb or gcintranet with no subtheme value)
1600- return this .getPartialCDNPath () + "cdts-styles.css" ;
1676+ return this .getPathAttributes ("href" , fileName );
16011677 }
16021678
16031679 /**
1604- * Return the CDN path to the cdts-[app-]styles.css file.
1680+ * Return the href/integrity/crossorigin attribute to the cdts-[app-]styles.css file.
16051681 *
16061682 * (Used by template files when rendering)
16071683 */
1608- public String getAppCssPath () {
1684+ public String getAppCssPathAttributes () {
16091685 if (this .isThemeGcWeb ()) {
1610- return this .getPartialCDNPath () + "cdts-app-styles.css" ;
1686+ return this .getPathAttributes ( "href" , "cdts-app-styles.css" ) ;
16111687 } else {
1612- return this .getCssPath ();
1688+ return this .getCssPathAttributes ();
16131689 }
16141690 }
16151691
16161692 /**
1617- * Return the CDN path to the cdts-splash-styles.css file.
1693+ * Return the href/integrity/crossorigin attribute to the cdts-splash-styles.css file.
16181694 *
16191695 * (Used by template files when rendering)
16201696 */
1621- public String getSplashCssPath () {
1622- return this .getPartialCDNPath () + "cdts-splash-styles.css" ;
1697+ public String getSplashCssPathAttributes () {
1698+ return this .getPathAttributes ( "href" , "cdts-splash-styles.css" ) ;
16231699 }
16241700
16251701 /**
16261702 * Returns the CDN path to the wet javascript file.
16271703 *
16281704 * (Used by template files when rendering)
16291705 */
1630- public String getWetJsPath () {
1631- return String .format ("%scompiled /wet-%s.js" , this .getPartialCDNPath (), this . getTwoLetterCultureLanguage ());
1706+ public String getWetJsPathAttributes () {
1707+ return this . getPathAttributes ( "src" , String .format ("compiled /wet-%s.js" , this .getTwoLetterCultureLanguage () ));
16321708 }
16331709
16341710 /**
@@ -1848,7 +1924,8 @@ private SetupBase buildSetupBase() {
18481924 return new SetupBase (JsonValueUtils .getNonEmptyString (this .getSubTheme ()),
18491925 this .getLoadJQueryFromGoogle () ? "external" : null , // jqueryEnv
18501926 this .getLeavingSecureSiteWarning (),
1851- this .getWebAnalytics ().isActive () ? Arrays .asList (this .getWebAnalytics ()) : null );
1927+ this .getWebAnalytics ().isActive () ? Arrays .asList (this .getWebAnalytics ()) : null ,
1928+ this .getUseSRI ()? null : false ); //if SRi is true, set to null to let CDTS's default be used
18521929 }
18531930
18541931 /**
@@ -2084,7 +2161,7 @@ public String getRenderServerSetup() {
20842161
20852162 return gson .toJson (new Setup (this .getCdtsCdnEnv (),
20862163 Mode .SERVER ,
2087- null , //base
2164+ this . getUseSRI ()? null : new SetupBase ( null , null , ( LeavingSecureSiteWarning ) null , null , false ), //base left null for defaults is SRI is true
20882165 null , //top
20892166 null , //preFooter
20902167 null , //footer
@@ -2104,7 +2181,7 @@ public String getRenderSplashSetup() {
21042181
21052182 return gson .toJson (new Setup (this .getCdtsCdnEnv (),
21062183 Mode .SPLASH ,
2107- null , //base
2184+ this . buildSetupBase () , //base
21082185 null , //top
21092186 null , //preFooter
21102187 null , //footer
0 commit comments