View Javadoc

1   /*
2    * Copyright 2011 University Corporation for Advanced Internet Development, Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package edu.internet2.middleware.shibboleth.idp.ui;
18  
19  import java.io.IOException;
20  import java.net.URI;
21  import java.net.URISyntaxException;
22  
23  import javax.servlet.jsp.JspException;
24  import javax.servlet.jsp.JspWriter;
25  import javax.servlet.jsp.tagext.BodyContent;
26  
27  import org.opensaml.samlext.saml2mdui.Logo;
28  import org.owasp.esapi.ESAPI;
29  import org.owasp.esapi.Encoder;
30  import org.slf4j.Logger;
31  import org.slf4j.LoggerFactory;
32  
33  /**Logo for the SP.*/
34  public class ServiceLogoTag extends ServiceTagSupport {
35  
36      /**
37       * checkstyle control.
38       */
39      private static final long serialVersionUID = 6451849117572923712L;
40      /** Class logger. */
41      private static Logger log = LoggerFactory.getLogger(ServiceLogoTag.class);
42      /** what to emit if the jsp has nothing. */
43      private static final String DEFAULT_VALUE = "";
44      /** what to emit as alt txt if all else fails. */
45      private static final String DEFAULT_ALT_TXT = "SP Logo";
46  
47      /** Bean storage. Size constraint X */
48      private int minWidth;
49      /** Bean storage. Size constraint X */
50      private int maxWidth = Integer.MAX_VALUE;
51      /** Bean storage. Size constraint Y */
52      private int minHeight;
53      /** Bean storage.  Size constraint Y */
54      private int maxHeight = Integer.MAX_VALUE;
55      /** Bean storage.  alt text */
56      private String altTxt;
57  
58      /** Bean setter.
59       * @param value what to set
60       */
61      public void setMaxWidth(Integer value) {
62          maxWidth = value.intValue();
63      }
64      /** Bean setter.
65       * @param value what to set
66       */
67      public void setMinWidth(Integer value) {
68          minWidth = value.intValue();
69      }
70      /** Bean setter.
71       * @param value what to set
72       */
73      public void setMinHeight(Integer value) {
74          minHeight = value.intValue();
75      }
76      /** Bean setter.
77       * @param value what to set
78       */
79      public void setMaxHeight(Integer value) {
80          maxHeight = value.intValue();
81      }
82  
83      /** Bean setter.
84       * @param value what to set
85       */
86      public void setAlt(String value) {
87          altTxt = value;
88      }
89  
90      /**
91       * Whether the provided logo fits inside the constraints.
92       * @param logo the logo
93       * @return whether it fits the provided max and mins
94       */
95      private boolean logoFits(Logo logo) {
96          return logo.getHeight() <= maxHeight && logo.getHeight() >= minHeight &&
97                 logo.getWidth() <= maxWidth && logo.getWidth() >= minWidth;
98      }
99      
100     /**
101      * get an appropriate Logo from UIInfo.
102      * @return the URL for a logo
103      */
104     private String getLogoFromUIInfo() {
105         String lang = getBrowserLanguage();
106 
107         if (getSPUIInfo() != null && getSPUIInfo().getDescriptions() != null) {
108             for (Logo logo:getSPUIInfo().getLogos()) {
109                 if (log.isDebugEnabled()){
110                     log.debug("Found logo in UIInfo, language=" + logo.getXMLLang() + 
111                             " width=" + logo.getWidth() + " height=" +logo.getHeight());
112                 }
113                 if (null != logo.getXMLLang() && !logo.getXMLLang().equals(lang)) {
114                     //
115                     // there is a language and its now what we want
116                     continue;
117                 }
118                 if (!logoFits(logo)) {
119                     //
120                     // size out of range
121                     //
122                     continue;
123                 }
124                 //
125                 // Found it
126                 //
127                 if (log.isDebugEnabled()) {
128                     log.debug("returning logo from UIInfo " + logo.getURL());
129                 }
130                 return logo.getURL();
131             }
132             if (log.isDebugEnabled()){
133                 log.debug("No appropriate logo in UIInfo");
134             }            
135         }
136         return null;
137     }
138     
139     /** Find what the user specified for alt txt.
140      * @return the text required
141      */
142     private String getAltText() {
143         
144         //
145         // First see what the user tried
146         //
147         String value = altTxt;
148         if (null != value && 0 != value.length()) {
149             return value;
150         }
151         
152         //
153         // Try the request
154         //
155         value = getServiceName();
156         if (null != value && 0 != value.length()) {
157             return value;
158         }
159         
160         return DEFAULT_ALT_TXT;
161     }
162 
163     /**
164      * Given the url build an appropriate &lta href=...
165      * @return the contrcuted hyperlink or null
166      */
167     private String getHyperlink() {
168         String url = getLogoFromUIInfo();
169         String encodedURL;
170         StringBuilder sb;
171         Encoder esapiEncoder = ESAPI.encoder();
172         
173         if (null == url) {
174             return null;
175         }
176         
177         try {
178             URI theUrl = new URI(url);
179             String scheme = theUrl.getScheme();
180     
181             if (!"http".equals(scheme) && !"https".equals(scheme) && !"mailto".equals(scheme)) {
182                 log.warn("The logo URL " + url + " contained an invalid scheme");
183                 return null;
184             }
185         } catch (URISyntaxException e) {
186             //
187             // Could not encode
188             //
189             log.warn("The logo URL " + url + " was not a URL " + e.toString());
190             return null;
191         }
192         
193         
194         encodedURL = esapiEncoder.encodeForHTMLAttribute(url);
195 
196         sb = new StringBuilder("<img src=\"");
197         sb.append(encodedURL).append('"');
198         sb.append("alt=").append(getAltText()).append('"');
199         addClassAndId(sb);
200         sb.append("/>");
201         return sb.toString();
202     }
203     
204     @Override
205     public int doEndTag() throws JspException {
206        
207         String result = getHyperlink();
208         
209         try {
210             if (null == result) {
211                 BodyContent bc = getBodyContent();
212                 boolean written = false;
213                 if (null != bc) {
214                     JspWriter ew= bc.getEnclosingWriter();
215                     if (ew != null) {
216                         bc.writeOut(ew);
217                         written = true;
218                     }
219                 }
220                 if (!written) {
221                     //
222                     // No value provided put in our own hardwired default
223                     //
224                     pageContext.getOut().print(DEFAULT_VALUE);
225                 }
226             } else {
227                 pageContext.getOut().print(result);
228             }
229         } catch (IOException e) {
230             log.warn("Error generating Description");
231             throw new JspException("EndTag", e);
232         }
233         return super.doEndTag();
234     }
235 }