View Javadoc

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