/** * ============LICENSE_START==================================================== * org.onap.aaf * =========================================================================== * Copyright (c) 2018 AT&T Intellectual Property. 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. * ============LICENSE_END==================================================== * */ package org.onap.aaf.auth.gui; import static org.onap.aaf.misc.xgen.html.HTMLGen.A; import static org.onap.aaf.misc.xgen.html.HTMLGen.H1; import static org.onap.aaf.misc.xgen.html.HTMLGen.LI; import static org.onap.aaf.misc.xgen.html.HTMLGen.TITLE; import static org.onap.aaf.misc.xgen.html.HTMLGen.UL; import java.io.IOException; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.onap.aaf.auth.common.Define; import org.onap.aaf.auth.env.AuthzEnv; import org.onap.aaf.auth.env.AuthzTrans; import org.onap.aaf.auth.rserv.CachingFileAccess; import org.onap.aaf.cadi.Permission; import org.onap.aaf.cadi.aaf.AAFPermission; import org.onap.aaf.cadi.config.Config; import org.onap.aaf.cadi.principal.TaggedPrincipal; import org.onap.aaf.misc.env.APIException; import org.onap.aaf.misc.env.Slot; import org.onap.aaf.misc.env.StaticSlot; import org.onap.aaf.misc.env.util.Split; import org.onap.aaf.misc.xgen.Cache; import org.onap.aaf.misc.xgen.CacheGen; import org.onap.aaf.misc.xgen.Code; import org.onap.aaf.misc.xgen.DynamicCode; import org.onap.aaf.misc.xgen.Mark; import org.onap.aaf.misc.xgen.html.HTMLCacheGen; import org.onap.aaf.misc.xgen.html.HTMLGen; import org.onap.aaf.misc.xgen.html.Imports; /** * A Base "Mobile First" Page * * @author Jonathan * */ public class Page extends HTMLCacheGen { public static final String AAFURL_TOOLS = "aaf_url.tools"; public static final String AAF_URL_TOOL_DOT = "aaf_url.tool."; public static final String AAF_URL_CUIGUI = "aaf_url.cuigui"; // link to help public static final String AAF_URL_GUI_ONBOARD = "aaf_url.gui_onboard"; public static final String AAF_URL_AAF_HELP = "aaf_url.aaf_help"; public static final String AAF_URL_CADI_HELP = "aaf_url.cadi_help"; public static final String PERM_CA_TYPE = Define.ROOT_NS() + ".ca"; public static enum BROWSER {iPhone,html5,ie,ieOld}; public static final int MAX_LINE=20; protected static final String[] NO_FIELDS = new String[0]; private static final String BROWSER_TYPE = "BROWSER_TYPE"; private final String bcName, bcUrl; private final String[] fields; public final boolean no_cache; // Note: Only access is synchronized in "getPerm" private final static Map> perms = new HashMap<>(); public String name() { return bcName; } public String url() { return bcUrl; } public String[] fields() { return fields; } public Page(AuthzEnv env, String name, String url, Enum[] en, final NamedCode ...content) throws APIException, IOException { super(CacheGen.PRETTY, new PageCode(env, 1, content)); fields = new String[en.length]; int i=-1; for(Enum p : en) { fields[++i]=p.name(); } bcName = name; bcUrl = url; // Mark which fields must be "no_cache" boolean no_cacheTemp=false; for(NamedCode nc : content) { if(nc.no_cache()) { no_cacheTemp=true; break; } } no_cache=no_cacheTemp; } public Page(AuthzEnv env, String name, String url, String [] fields, final NamedCode ... content) throws APIException,IOException { this(env,name,url,1,fields,content); } public Page(AuthzEnv env, String name, String url, int backdots, String [] fields, final NamedCode ... content) throws APIException,IOException { super(CacheGen.PRETTY, new PageCode(env, backdots, content)); if(fields==null) { this.fields = new String[0]; } else { this.fields = fields; } bcName = name; bcUrl = url; // Mark which fields must be "no_cache" boolean no_cacheTemp=false; for(NamedCode nc : content) { if(nc.no_cache()) { no_cacheTemp=true; break; } } no_cache=no_cacheTemp; } private static class PageCode implements Code { private static final String AAF_GUI_TITLE = "aaf_gui_title"; private final ContentCode[] content; private final Slot browserSlot; private final int backdots; protected AuthzEnv env; private StaticSlot sTheme; public PageCode(AuthzEnv env, int backdots, final ContentCode[] content) { this.content = content; this.backdots = backdots; browserSlot = env.slot(BROWSER_TYPE); sTheme = env.staticSlot(CachingFileAccess.CFA_WEB_PATH); this.env = env; } @Override public void code(final Cache cache, final HTMLGen hgen) throws APIException, IOException { // Note: I found that App Storage saves everything about the page, or not. Thus, if you declare the page uncacheable, none of the // Artifacts, like JPGs are stored, which makes this feature useless for Server driven elements cache.dynamic(hgen, new DynamicCode() { @Override public void code(AAF_GUI state, AuthzTrans trans, final Cache cache, final HTMLGen hgen) throws APIException, IOException { switch(browser(trans,browserSlot)) { case ieOld: case ie: hgen.directive("!DOCTYPE html"); hgen.directive("meta", "http-equiv=X-UA-Compatible","content=IE=11"); default: } } }); hgen.html(); final String title = env.getProperty(AAF_GUI_TITLE,"Authentication/Authorization Framework"); final String theme = env.get(sTheme); Mark head = hgen.head(); hgen.leaf(TITLE).text(title).end(); hgen.imports(new Imports(backdots).css(theme + "/aaf5.css") .js(theme + "/comm.js") .js(theme + "/console.js") .js(theme + "/common.js")); cache.dynamic(hgen, new DynamicCode() { @Override public void code(AAF_GUI state, AuthzTrans trans, final Cache cache, final HTMLGen hgen) throws APIException, IOException { switch(browser(trans,browserSlot)) { case iPhone: hgen.imports(new Imports(backdots).css(theme + "/aaf5iPhone.css")); break; case ie: case ieOld: hgen.js().text("document.createElement('header');") .text("document.createElement('nav');") .done(); case html5: hgen.imports(new Imports(backdots).css(theme + "/aaf5Desktop.css")); break; } } }); hgen.end(head); Mark body = hgen.body(); Mark header = hgen.header(); cache.dynamic(hgen, new DynamicCode() { @Override public void code(AAF_GUI state, AuthzTrans trans,Cache cache, HTMLGen xgen) throws APIException, IOException { // Obtain Server Info, and print // AT&T Only String env = trans.getProperty(Config.AAF_ENV,"N/A"); xgen.leaf(H1).text(title + " on " + env).end(); xgen.leaf("p","id=version").text("AAF Version: " + state.deployedVersion).end(); // Obtain User Info, and print TaggedPrincipal p = trans.getUserPrincipal(); String user,secured; if(p==null) { user = "please choose a Login Authority"; secured = "NOT Secure!"; } else { user = p.personalName(); secured = p.tag(); } xgen.leaf("p","id=welcome").text("Welcome, ") .text(user) .text("") .text(secured) .text("").end(); switch(browser(trans,browserSlot)) { case ieOld: case ie: xgen.incr("h5").text("This app is Mobile First HTML5. Internet Explorer " + " does not support all HTML5 standards. Old, non TSS-Standard versions may not function correctly.").br() .text(" For best results, use a highly compliant HTML5 browser like Firefox.") .end(); break; default: } } }); hgen.hr(); int cIdx; ContentCode nc; // If BreadCrumbs, put here if(content.length>0 && content[0] instanceof BreadCrumbs) { nc = content[0]; Mark ctnt = hgen.divID(nc.idattrs()); nc.code(cache, hgen); hgen.end(ctnt); cIdx = 1; } else { cIdx = 0; } hgen.end(header); Mark inner = hgen.divID("inner"); // Content for(int i=cIdx;i=0 * * Use int found in "ieVersion" * * Official IE 7 * Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; * .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729) * Official IE 8 * Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; * .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; ATT) * * IE 11 Compatibility * Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; SLCC2; .NET CLR 2.0.50727; * .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET CLR 1.1.4322; .NET4.0C; .NET4.0E; InfoPath.3; HVD; ATT) * * IE 11 (not Compatiblity) * Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; * .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET CLR 1.1.4322; .NET4.0C; .NET4.0E; InfoPath.3; HVD; ATT) * * @param trans * @return */ public static BROWSER browser(AuthzTrans trans, Slot slot) { BROWSER br = trans.get(slot, null); if(br==null) { String agent = trans.agent(); int msie; if(agent.contains("iPhone") /* other phones? */) { br=BROWSER.iPhone; } else if ((msie = agent.indexOf("MSIE"))>=0) { msie+=5; int end = agent.indexOf(";",msie); float ver; try { ver = Float.valueOf(agent.substring(msie,end)); br = ver<8f?BROWSER.ieOld:BROWSER.ie; } catch (Exception e) { br = BROWSER.ie; } } else { br = BROWSER.html5; } trans.put(slot,br); } return br; } /* * Get, rather than create each time, permissions for validations */ protected static synchronized Permission getPerm(String instance, String action) { Map msp = perms.get(instance); Permission p; if(msp==null) { msp = new HashMap<>(); perms.put(instance, msp); p=null; } else { p = msp.get(instance); } if(p==null) { p=new AAFPermission(PERM_CA_TYPE,instance,action); msp.put(action, p); } return p; } protected static String getSingleParam(HttpServletRequest req, String tag) { String values[] = req.getParameterValues(tag); return values.length<1?null:values[0]; } }