Skip to content

Commit f7ce4f7

Browse files
authored
Merge pull request #23 from wet-boew/21-add-support-for-sri
21 add support for sri
2 parents e27cb8f + 3a65007 commit f7ce4f7

30 files changed

Lines changed: 294 additions & 225 deletions

File tree

gocwebtemplate-core/gocwebtemplate-core-base/src/main/java/goc/webtemplate/component/AbstractCoreBean.java

Lines changed: 106 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import goc.webtemplate.component.jsonentities.AppFooter;
3737
import goc.webtemplate.component.jsonentities.AppTop;
3838
import goc.webtemplate.component.jsonentities.CDTSEnvironment;
39+
import goc.webtemplate.component.jsonentities.CDTSEnvironmentList;
3940
import goc.webtemplate.component.jsonentities.FeedbackLink;
4041
import goc.webtemplate.component.jsonentities.Footer;
4142
import goc.webtemplate.component.jsonentities.IPreFooter;
@@ -62,9 +63,13 @@
6263
*/
6364
public 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

Comments
 (0)