Coverage Report - org.kuali.rice.kns.util.WebUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
WebUtils
0%
0/314
0%
0/164
3.333
 
 1  
 /*
 2  
  * Copyright 2005-2007 The Kuali Foundation
 3  
  * 
 4  
  * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
 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  
 package org.kuali.rice.kns.util;
 17  
 
 18  
 import java.io.ByteArrayOutputStream;
 19  
 import java.io.IOException;
 20  
 import java.io.InputStream;
 21  
 import java.io.OutputStream;
 22  
 import java.util.Arrays;
 23  
 import java.util.Collection;
 24  
 import java.util.Enumeration;
 25  
 import java.util.HashMap;
 26  
 import java.util.Hashtable;
 27  
 import java.util.Iterator;
 28  
 import java.util.List;
 29  
 import java.util.Map;
 30  
 import java.util.Set;
 31  
 import java.util.regex.Matcher;
 32  
 import java.util.regex.Pattern;
 33  
 
 34  
 import javax.servlet.ServletException;
 35  
 import javax.servlet.http.HttpServletRequest;
 36  
 import javax.servlet.http.HttpServletResponse;
 37  
 import javax.servlet.http.HttpSession;
 38  
 import javax.servlet.jsp.PageContext;
 39  
 
 40  
 import org.apache.commons.lang.StringEscapeUtils;
 41  
 import org.apache.commons.lang.StringUtils;
 42  
 import org.apache.log4j.Level;
 43  
 import org.apache.log4j.Logger;
 44  
 import org.apache.struts.Globals;
 45  
 import org.apache.struts.action.ActionForm;
 46  
 import org.apache.struts.action.ActionMapping;
 47  
 import org.apache.struts.action.ActionServletWrapper;
 48  
 import org.apache.struts.upload.CommonsMultipartRequestHandler;
 49  
 import org.apache.struts.upload.FormFile;
 50  
 import org.apache.struts.upload.MultipartRequestHandler;
 51  
 import org.apache.struts.upload.MultipartRequestWrapper;
 52  
 import org.kuali.rice.kns.datadictionary.AttributeDefinition;
 53  
 import org.kuali.rice.kns.datadictionary.AttributeSecurity;
 54  
 import org.kuali.rice.kns.datadictionary.DataDictionary;
 55  
 import org.kuali.rice.kns.datadictionary.DataDictionaryEntryBase;
 56  
 import org.kuali.rice.kns.datadictionary.DocumentEntry;
 57  
 import org.kuali.rice.kns.datadictionary.mask.MaskFormatter;
 58  
 import org.kuali.rice.kns.document.Document;
 59  
 import org.kuali.rice.kns.document.authorization.DocumentAuthorizer;
 60  
 import org.kuali.rice.kns.exception.FileUploadLimitExceededException;
 61  
 import org.kuali.rice.kns.exception.ValidationException;
 62  
 import org.kuali.rice.kns.service.KNSServiceLocator;
 63  
 import org.kuali.rice.kns.service.KualiConfigurationService;
 64  
 import org.kuali.rice.kns.service.ParameterConstants;
 65  
 import org.kuali.rice.kns.service.ParameterService;
 66  
 import org.kuali.rice.kns.web.struts.action.KualiMultipartRequestHandler;
 67  
 import org.kuali.rice.kns.web.struts.form.KualiDocumentFormBase;
 68  
 import org.kuali.rice.kns.web.struts.form.KualiForm;
 69  
 import org.kuali.rice.kns.web.struts.form.KualiMaintenanceForm;
 70  
 import org.kuali.rice.kns.web.struts.pojo.PojoFormBase;
 71  
 
 72  
 /**
 73  
  * General helper methods for handling requests.
 74  
  */
 75  0
 public class WebUtils {
 76  0
     private static final Logger LOG = Logger.getLogger(WebUtils.class);
 77  
 
 78  
     private static final String IMAGE_COORDINATE_CLICKED_X_EXTENSION = ".x";
 79  
     private static final String IMAGE_COORDINATE_CLICKED_Y_EXTENSION = ".y";
 80  
     
 81  
     private static final String APPLICATION_IMAGE_URL_PROPERTY_PREFIX = "application.custom.image.url";
 82  
     private static final String DEFAULT_IMAGE_URL_PROPERTY_NAME = "kr.externalizable.images.url";
 83  
     
 84  
     /**
 85  
      * A request attribute name that indicates that a {@link FileUploadLimitExceededException} has already been thrown for the request.
 86  
      */
 87  
     public static final String FILE_UPLOAD_LIMIT_EXCEEDED_EXCEPTION_ALREADY_THROWN = "fileUploadLimitExceededExceptionAlreadyThrown";
 88  
     
 89  
     private static KualiConfigurationService configurationService;
 90  
     
 91  
     /**
 92  
      * Checks for methodToCall parameter, and picks off the value using set dot notation. Handles the problem of image submits.
 93  
      * 
 94  
      * @param request
 95  
      * @return methodToCall String
 96  
      */
 97  
     public static String parseMethodToCall(ActionForm form, HttpServletRequest request) {
 98  0
         String methodToCall = null;
 99  
         
 100  
         // check if is specified cleanly
 101  0
         if (StringUtils.isNotBlank(request.getParameter(KNSConstants.DISPATCH_REQUEST_PARAMETER))) {
 102  0
                 if (form instanceof KualiForm && !((KualiForm) form).shouldMethodToCallParameterBeUsed(KNSConstants.DISPATCH_REQUEST_PARAMETER,
 103  
                                         request.getParameter(KNSConstants.DISPATCH_REQUEST_PARAMETER), request)) {
 104  0
                             throw new RuntimeException("Cannot verify that the methodToCall should be " + request.getParameter(KNSConstants.DISPATCH_REQUEST_PARAMETER));
 105  
                 }
 106  0
                     methodToCall = request.getParameter(KNSConstants.DISPATCH_REQUEST_PARAMETER);
 107  
                     // include .x at the end of the parameter to make it consistent w/ other parameters
 108  0
                     request.setAttribute(KNSConstants.METHOD_TO_CALL_ATTRIBUTE, KNSConstants.DISPATCH_REQUEST_PARAMETER + "." + methodToCall + IMAGE_COORDINATE_CLICKED_X_EXTENSION);
 109  
         }
 110  
 
 111  
         /**
 112  
          * The reason why we are checking for a ".x" at the end of the parameter name:
 113  
          * It is for the image names that in addition to sending the form data, 
 114  
          * the web browser sends the x,y coordinate of where the user clicked on the image. 
 115  
          * If the image input is not given a name then the browser sends the x and y coordinates as the "x" and "y" input fields. 
 116  
          * If the input image does have a name, the x and y coordinates are sent using the format name.x and name.y. 
 117  
          */
 118  0
         if (methodToCall == null) {
 119  
             // iterate through parameters looking for methodToCall
 120  0
             for (Enumeration i = request.getParameterNames(); i.hasMoreElements();) {
 121  0
                 String parameterName = (String) i.nextElement();
 122  
 
 123  
                 // check if the parameter name is a specifying the methodToCall
 124  0
                 if (isMethodToCall(parameterName)) {
 125  0
                     methodToCall = getMethodToCallSettingAttribute(form, request, parameterName);
 126  0
                     break; 
 127  
                 } else { 
 128  
                     // KULRICE-1218: Check if the parameter's values match (not just the name)
 129  0
                     for (String value : request.getParameterValues(parameterName)) {
 130  
                             //adding period to startsWith check - don't want to get confused with methodToCallFoobar
 131  0
                         if (isMethodToCall(value)) {
 132  0
                                 methodToCall = getMethodToCallSettingAttribute(form, request, value);
 133  
                                 //why is there not a break outer loop here?
 134  
                         }
 135  
                     }
 136  
                 }
 137  0
             }
 138  
         }
 139  
         
 140  0
         return methodToCall;
 141  
     }
 142  
     
 143  
     /** 
 144  
      * Checks if a string signifies a methodToCall string
 145  
      * 
 146  
      * @param string the string to check
 147  
      * @return true if is a methodToCall
 148  
      */
 149  
     private static boolean isMethodToCall(String string) {
 150  
             //adding period to startsWith check - don't want to get confused with methodToCallFoobar
 151  0
             return string.startsWith(KNSConstants.DISPATCH_REQUEST_PARAMETER  + ".");
 152  
     }
 153  
 
 154  
     /**
 155  
      * Parses out the methodToCall command and also sets the request attribute for the methodToCall.
 156  
      * 
 157  
      * @param form the ActionForm
 158  
      * @param request the request to set the attribute on
 159  
      * @param string the methodToCall string
 160  
      * @return the methodToCall command
 161  
      */
 162  
     private static String getMethodToCallSettingAttribute(ActionForm form, HttpServletRequest request, String string) {
 163  
             
 164  0
             if (form instanceof ActionForm && !((KualiForm) form).shouldMethodToCallParameterBeUsed(string, request.getParameter(string), request)) {
 165  0
                         throw new RuntimeException("Cannot verify that the methodToCall should be " + string);
 166  
                 }
 167  
             //always adding a coordinate even if not an image
 168  0
             final String attributeValue = endsWithCoordinates(string) ? string : string + IMAGE_COORDINATE_CLICKED_X_EXTENSION;
 169  0
             final String methodToCall = StringUtils.substringBetween(attributeValue, KNSConstants.DISPATCH_REQUEST_PARAMETER + ".", ".");
 170  0
         request.setAttribute(KNSConstants.METHOD_TO_CALL_ATTRIBUTE, attributeValue);
 171  0
         return methodToCall;
 172  
     }
 173  
 
 174  
     /**
 175  
      * Iterates through and logs (at the given level) all attributes and parameters of the given request onto the given Logger
 176  
      * 
 177  
      * @param request
 178  
      * @param logger
 179  
      */
 180  
     public static void logRequestContents(Logger logger, Level level, HttpServletRequest request) {
 181  0
         if (logger.isEnabledFor(level)) {
 182  0
             logger.log(level, "--------------------");
 183  0
             logger.log(level, "HttpRequest attributes:");
 184  0
             for (Enumeration e = request.getAttributeNames(); e.hasMoreElements();) {
 185  0
                 String attrName = (String) e.nextElement();
 186  0
                 Object attrValue = request.getAttribute(attrName);
 187  
 
 188  0
                 if (attrValue.getClass().isArray()) {
 189  0
                     logCollection(logger, level, attrName, Arrays.asList((Object[]) attrValue));
 190  
                 }
 191  0
                 else if (attrValue instanceof Collection) {
 192  0
                     logCollection(logger, level, attrName, (Collection) attrValue);
 193  
                 }
 194  0
                 else if (attrValue instanceof Map) {
 195  0
                     logMap(logger, level, attrName, (Map) attrValue);
 196  
                 }
 197  
                 else {
 198  0
                     logObject(logger, level, attrName, attrValue);
 199  
                 }
 200  0
             }
 201  
 
 202  0
             logger.log(level, "--------------------");
 203  0
             logger.log(level, "HttpRequest parameters:");
 204  0
             for (Enumeration i = request.getParameterNames(); i.hasMoreElements();) {
 205  0
                 String paramName = (String) i.nextElement();
 206  0
                 String[] paramValues = (String[]) request.getParameterValues(paramName);
 207  
 
 208  0
                 logArray(logger, level, paramName, paramValues);
 209  0
             }
 210  
 
 211  0
             logger.log(level, "--------------------");
 212  
         }
 213  0
     }
 214  
 
 215  
 
 216  
     private static void logArray(Logger logger, Level level, String arrayName, Object[] array) {
 217  0
         StringBuffer value = new StringBuffer("[");
 218  0
         for (int i = 0; i < array.length; ++i) {
 219  0
             if (i > 0) {
 220  0
                 value.append(",");
 221  
             }
 222  0
             value.append(array[i]);
 223  
         }
 224  0
         value.append("]");
 225  
 
 226  0
         logThing(logger, level, arrayName, value);
 227  0
     }
 228  
 
 229  
     private static void logCollection(Logger logger, Level level, String collectionName, Collection c) {
 230  0
         StringBuffer value = new StringBuffer("{");
 231  0
         for (Iterator i = c.iterator(); i.hasNext();) {
 232  0
             value.append(i.next());
 233  0
             if (i.hasNext()) {
 234  0
                 value.append(",");
 235  
             }
 236  
         }
 237  0
         value.append("}");
 238  
 
 239  0
         logThing(logger, level, collectionName, value);
 240  0
     }
 241  
 
 242  
     private static void logMap(Logger logger, Level level, String mapName, Map m) {
 243  0
         StringBuffer value = new StringBuffer("{");
 244  0
         for (Iterator i = m.entrySet().iterator(); i.hasNext();) {
 245  0
             Map.Entry e = (Map.Entry) i.next();
 246  0
             value.append("('" + e.getKey() + "','" + e.getValue() + "')");
 247  0
         }
 248  0
         value.append("}");
 249  
 
 250  0
         logThing(logger, level, mapName, value);
 251  0
     }
 252  
 
 253  
     private static void logObject(Logger logger, Level level, String objectName, Object o) {
 254  0
         logThing(logger, level, objectName, "'" + o + "'");
 255  0
     }
 256  
 
 257  
     private static void logThing(Logger logger, Level level, String thingName, Object thing) {
 258  0
         logger.log(level, "    '" + thingName + "' => " + thing);
 259  0
     }
 260  
 
 261  
     /**
 262  
      * A file that is not of type text/plain or text/html can be output through the response using this method.
 263  
      * 
 264  
      * @param response
 265  
      * @param contentType
 266  
      * @param outStream
 267  
      * @param fileName
 268  
      */
 269  
     public static void saveMimeOutputStreamAsFile(HttpServletResponse response, String contentType, ByteArrayOutputStream byteArrayOutputStream, String fileName) throws IOException {
 270  
 
 271  
         // set response
 272  0
         response.setContentType(contentType);
 273  0
         response.setHeader("Content-disposition", "attachment; filename=" + fileName);
 274  0
         response.setHeader("Expires", "0");
 275  0
         response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
 276  0
         response.setHeader("Pragma", "public");
 277  0
         response.setContentLength(byteArrayOutputStream.size());
 278  
 
 279  
         // write to output
 280  0
         OutputStream outputStream = response.getOutputStream();
 281  0
         byteArrayOutputStream.writeTo(response.getOutputStream());
 282  0
         outputStream.flush();
 283  0
         outputStream.close();
 284  0
     }
 285  
 
 286  
     /**
 287  
      * A file that is not of type text/plain or text/html can be output through the response using this method.
 288  
      * 
 289  
      * @param response
 290  
      * @param contentType
 291  
      * @param outStream
 292  
      * @param fileName
 293  
      */
 294  
     public static void saveMimeInputStreamAsFile(HttpServletResponse response, String contentType, InputStream inStream, String fileName, int fileSize) throws IOException {
 295  
 
 296  
         // set response
 297  0
         response.setContentType(contentType);
 298  0
         response.setHeader("Content-disposition", "attachment; filename=" + fileName);
 299  0
         response.setHeader("Expires", "0");
 300  0
         response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
 301  0
         response.setHeader("Pragma", "public");
 302  0
         response.setContentLength(fileSize);
 303  
 
 304  
         // write to output
 305  0
         OutputStream out = response.getOutputStream();
 306  0
         while (inStream.available() > 0) {
 307  0
             out.write(inStream.read());
 308  
         }
 309  0
         out.flush();
 310  0
     }
 311  
     
 312  
     /**
 313  
      * JSTL function to return the tab state of the tab from the form. 
 314  
      * 
 315  
      * @param form
 316  
      * @param tabKey
 317  
      * @return
 318  
      */
 319  
     public static String getTabState(KualiForm form, String tabKey) {
 320  0
         return form.getTabState(tabKey);
 321  
     }
 322  
     
 323  
     public static void incrementTabIndex(KualiForm form, String tabKey) {
 324  0
             form.incrementTabIndex();
 325  0
     }
 326  
     
 327  
     /**
 328  
      * Generates a String from the title that can be used as a Map key.
 329  
      * 
 330  
      * @param tabTitle
 331  
      * @return
 332  
      */
 333  
     public static String generateTabKey(String tabTitle) {
 334  0
         String key = "";
 335  0
         if (!StringUtils.isBlank(tabTitle)) {
 336  0
             key = tabTitle.replaceAll("\\W", "");
 337  
 //            if (key.length() > 25) {
 338  
 //                key = key.substring(0, 24);
 339  
 //            }
 340  
         }
 341  
         
 342  0
         return key;
 343  
     }
 344  
 
 345  
     public static void getMultipartParameters(HttpServletRequest request, ActionServletWrapper servletWrapper, ActionForm form, ActionMapping mapping) {
 346  0
         Map params = new HashMap();
 347  
 
 348  
         // Get the ActionServletWrapper from the form bean
 349  
         //ActionServletWrapper servletWrapper = getServletWrapper();
 350  
         
 351  
         try {                            
 352  0
                 CommonsMultipartRequestHandler multipartHandler = new CommonsMultipartRequestHandler();  
 353  0
             if (multipartHandler != null) {        
 354  
                 // Set servlet and mapping info
 355  0
                 if (servletWrapper != null) {
 356  
                     // from pojoformbase
 357  
                     // servlet only affects tempdir on local disk
 358  0
                     servletWrapper.setServletFor(multipartHandler);
 359  
                 }
 360  0
                 multipartHandler.setMapping((ActionMapping) request.getAttribute(Globals.MAPPING_KEY));
 361  
                 // Initialize multipart request class handler
 362  0
                 multipartHandler.handleRequest(request);
 363  
                
 364  0
                 Collection<FormFile> files = multipartHandler.getFileElements().values();
 365  0
                 Enumeration keys = multipartHandler.getFileElements().keys();
 366  
                 
 367  
                 
 368  0
                 while(keys.hasMoreElements()){
 369  0
                         Object key = keys.nextElement();
 370  0
                         FormFile file = (FormFile)multipartHandler.getFileElements().get(key);
 371  0
                         long maxSize = WebUtils.getMaxUploadSize(form);
 372  0
                         if (LOG.isDebugEnabled()) {
 373  0
                                 LOG.debug(file.getFileSize());
 374  
                         }
 375  0
                         if (maxSize > 0 && Long.parseLong(file.getFileSize()+"") > maxSize ) {
 376  
                                 
 377  0
                         GlobalVariables.getMessageMap().putError(key.toString(),
 378  
                                         RiceKeyConstants.ERROR_UPLOADFILE_SIZE,
 379  
                                 new String[] {
 380  
                                 file.getFileName(), Long.toString(maxSize)});
 381  
                       
 382  
                     }
 383  0
                 }
 384  
               
 385  
                 // get file elements for kualirequestprocessor
 386  0
                 if (servletWrapper == null) {
 387  0
                     request.setAttribute(KNSConstants.UPLOADED_FILE_REQUEST_ATTRIBUTE_KEY,getFileParametersForMultipartRequest(request, multipartHandler));
 388  
                 }
 389  
             }
 390  
         }
 391  0
         catch (ServletException e) {
 392  0
             throw new ValidationException("unable to handle multipart request " + e.getMessage(),e);
 393  0
         }
 394  0
     }
 395  
 
 396  
     public static long getMaxUploadSize(ActionForm form){
 397  0
             long max = 0L;
 398  0
              KualiMultipartRequestHandler multipartHandler = new KualiMultipartRequestHandler();
 399  0
          if (form instanceof PojoFormBase) {
 400  0
              max = multipartHandler.calculateMaxUploadSizeToMaxOfList( ((PojoFormBase) form).getMaxUploadSizes() );
 401  
          }
 402  0
          if ( LOG.isDebugEnabled() ) {
 403  0
              LOG.debug( "Max File Upload Size: " + max );
 404  
          }
 405  0
          return  max;
 406  
     }
 407  
     
 408  
     private static KualiMultipartRequestHandler getMultipartHandler(HttpServletRequest request, ActionForm form) throws ServletException {
 409  0
         KualiMultipartRequestHandler multipartHandler = new KualiMultipartRequestHandler();
 410  0
         if (form instanceof PojoFormBase) {
 411  
            // multipartHandler.setMaxUploadSizeToMaxOfList( ((PojoFormBase) form).getMaxUploadSizes() );
 412  
         }
 413  0
         if ( LOG.isDebugEnabled() ) {
 414  0
             LOG.debug( "Max File Upload Size: " + multipartHandler.getSizeMaxString() );
 415  
         }
 416  0
         return multipartHandler;
 417  
     }
 418  
 
 419  
     private static Map getFileParametersForMultipartRequest(HttpServletRequest request, MultipartRequestHandler multipartHandler) {
 420  0
         Map parameters = new HashMap();
 421  0
         Hashtable elements = multipartHandler.getFileElements();
 422  0
         Enumeration e = elements.keys();
 423  0
         while (e.hasMoreElements()) {
 424  0
             String key = (String) e.nextElement();
 425  0
             parameters.put(key, elements.get(key));
 426  0
         }
 427  
 
 428  0
         if (request instanceof MultipartRequestWrapper) {
 429  0
             request = ((MultipartRequestWrapper) request).getRequest();
 430  0
             e = request.getParameterNames();
 431  0
             while (e.hasMoreElements()) {
 432  0
                 String key = (String) e.nextElement();
 433  0
                 parameters.put(key, request.getParameterValues(key));
 434  0
             }
 435  
         }
 436  
         else {
 437  0
             LOG.debug("Gathering multipart parameters for unwrapped request");
 438  
         }
 439  0
         return parameters;
 440  
     }
 441  
 
 442  
 
 443  
     // end multipart
 444  
     
 445  
     public static void registerEditableProperty(PojoFormBase form, String editablePropertyName){
 446  0
             form.registerEditableProperty(editablePropertyName);
 447  0
     }
 448  
     
 449  
     public static boolean isDocumentSession(Document document, PojoFormBase docForm){
 450  0
                 boolean sessionDoc = document instanceof org.kuali.rice.kns.document.SessionDocument;
 451  0
                 boolean dataDictionarySessionDoc = false;
 452  0
                 if (!sessionDoc) {
 453  0
                         DocumentEntry documentEntry = null;
 454  0
                         DataDictionary dataDictionary = KNSServiceLocator.getDataDictionaryService().getDataDictionary();
 455  0
                         if (docForm instanceof KualiMaintenanceForm) {
 456  0
                                 KualiMaintenanceForm maintenanceForm = (KualiMaintenanceForm) docForm;
 457  0
                                 if (dataDictionary != null) {
 458  0
                                     if (maintenanceForm.getDocTypeName() != null) {
 459  0
                                             documentEntry = dataDictionary.getDocumentEntry(maintenanceForm.getDocTypeName());
 460  0
                                             dataDictionarySessionDoc = documentEntry.isSessionDocument();
 461  
                                     }
 462  
                                 }
 463  0
                         } else {
 464  0
                                 if (document!=null && dataDictionary != null) {
 465  0
                                         documentEntry = dataDictionary.getDocumentEntry(document.getClass().getName());
 466  0
                                         dataDictionarySessionDoc = documentEntry.isSessionDocument();
 467  
                                 }
 468  
                         }
 469  
                 }
 470  0
                 return sessionDoc || dataDictionarySessionDoc;
 471  
     }
 472  
     
 473  
     public static boolean isFormSessionDocument(PojoFormBase form){
 474  0
             Document document = null;
 475  0
             if (KualiDocumentFormBase.class.isAssignableFrom(form.getClass())) {
 476  0
                         KualiDocumentFormBase docForm = (KualiDocumentFormBase)form;
 477  0
                         document = docForm.getDocument();
 478  
             }
 479  0
             return isDocumentSession(document, form);
 480  
     }
 481  
     
 482  0
     public static String KEY_KUALI_FORM_IN_SESSION = "KualiForm";
 483  
     public static ActionForm getKualiForm(PageContext pageContext){
 484  0
             return getKualiForm((HttpServletRequest)pageContext.getRequest());
 485  
     }
 486  
     
 487  
     public static ActionForm getKualiForm(HttpServletRequest request){
 488  0
             if(request.getAttribute(KEY_KUALI_FORM_IN_SESSION)!=null) {
 489  0
                     return (ActionForm)request.getAttribute(KEY_KUALI_FORM_IN_SESSION);
 490  
             } else {
 491  0
                     final HttpSession session = request.getSession(false);
 492  0
                     return session != null ? (ActionForm) session.getAttribute(KEY_KUALI_FORM_IN_SESSION) : null;
 493  
             }
 494  
     }
 495  
     
 496  
     public static boolean isPropertyEditable(Set<String> editableProperties, String propertyName){
 497  0
             if (LOG.isDebugEnabled()) {
 498  0
                     LOG.debug("isPropertyEditable("+ propertyName+")");
 499  
             }
 500  
             
 501  0
             boolean returnVal = editableProperties == null || editableProperties.contains(propertyName) ||
 502  
                             (getIndexOfCoordinateExtension(propertyName)==-1?false:
 503  
                                     editableProperties.contains(
 504  
                                                     propertyName.substring(0, getIndexOfCoordinateExtension(propertyName))));
 505  0
             if ( !returnVal ) {
 506  0
                 if (LOG.isDebugEnabled()) {
 507  0
                         LOG.debug("isPropertyEditable("+propertyName+") == false / editableProperties: "+editableProperties);
 508  
                 }
 509  
             }
 510  0
             return returnVal;
 511  
     }
 512  
     
 513  
     public static boolean endsWithCoordinates(String parameter){
 514  0
             return parameter.endsWith(WebUtils.IMAGE_COORDINATE_CLICKED_X_EXTENSION) ||
 515  
                             parameter.endsWith(WebUtils.IMAGE_COORDINATE_CLICKED_Y_EXTENSION);
 516  
     }
 517  
 
 518  
     public static int getIndexOfCoordinateExtension(String parameter){
 519  0
                 int indexOfCoordinateExtension = parameter.lastIndexOf(WebUtils.IMAGE_COORDINATE_CLICKED_X_EXTENSION);
 520  0
                 if(indexOfCoordinateExtension==-1)
 521  0
                         indexOfCoordinateExtension = parameter.lastIndexOf(WebUtils.IMAGE_COORDINATE_CLICKED_Y_EXTENSION);
 522  0
                 return indexOfCoordinateExtension;
 523  
     }
 524  
     
 525  
     public static boolean isInquiryHiddenField(String className, String fieldName, Object formObject, String propertyName) {
 526  0
             boolean isHidden = false;
 527  0
             String hiddenInquiryFields = getKualiConfigurationService().getPropertyString(className+".hidden");
 528  0
             if (StringUtils.isEmpty(hiddenInquiryFields)) {
 529  0
                     return isHidden;
 530  
             }
 531  0
             List hiddenFields = Arrays.asList(hiddenInquiryFields.replaceAll(" ", "").split(","));
 532  0
             if (hiddenFields.contains(fieldName.trim())) {
 533  0
                     isHidden = true;
 534  
             }
 535  0
             return isHidden;
 536  
     }
 537  
     
 538  
     public static boolean isHiddenKimObjectType(String type, String configParameter) {
 539  0
             boolean hideType = false;
 540  0
             String hiddenTypes = getKualiConfigurationService().getPropertyString(configParameter);
 541  0
             if (StringUtils.isEmpty(hiddenTypes)) {
 542  0
                     return hideType;
 543  
             }
 544  0
             List hiddenTypeValues = Arrays.asList(hiddenTypes.replaceAll(" ", "").split(","));
 545  0
             if (hiddenTypeValues.contains(type.trim())) {
 546  0
                     hideType = true;
 547  
             }
 548  0
             return hideType;
 549  
     }
 550  
     
 551  
     
 552  
     public static String getFullyMaskedValue(String className, String fieldName, Object formObject, String propertyName){
 553  0
             String displayMaskValue = null;
 554  0
             Object propertyValue = ObjectUtils.getPropertyValue(formObject, propertyName);
 555  
             
 556  0
             DataDictionaryEntryBase entry = (DataDictionaryEntryBase) KNSServiceLocator.getDataDictionaryService().getDataDictionary().getDictionaryObjectEntry(className);
 557  0
             AttributeDefinition a = entry.getAttributeDefinition(fieldName);
 558  
             
 559  0
             AttributeSecurity attributeSecurity = a.getAttributeSecurity();
 560  0
             if(attributeSecurity != null && attributeSecurity.isMask()){
 561  0
                     MaskFormatter maskFormatter = attributeSecurity.getMaskFormatter();
 562  0
                     displayMaskValue =  maskFormatter.maskValue(propertyValue);
 563  
                     
 564  
             }        
 565  0
             return displayMaskValue;
 566  
     }
 567  
     
 568  
     public static String getPartiallyMaskedValue(String className, String fieldName, Object formObject, String propertyName){
 569  0
             String displayMaskValue = null;
 570  0
             Object propertyValue = ObjectUtils.getPropertyValue(formObject, propertyName);
 571  
             
 572  0
             DataDictionaryEntryBase entry = (DataDictionaryEntryBase) KNSServiceLocator.getDataDictionaryService().getDataDictionary().getDictionaryObjectEntry(className);
 573  0
             AttributeDefinition a = entry.getAttributeDefinition(fieldName);
 574  
             
 575  0
             AttributeSecurity attributeSecurity = a.getAttributeSecurity();
 576  0
             if(attributeSecurity != null && attributeSecurity.isPartialMask()){
 577  0
                     MaskFormatter partialMaskFormatter = attributeSecurity.getPartialMaskFormatter();
 578  0
                     displayMaskValue =  partialMaskFormatter.maskValue(propertyValue);
 579  
                     
 580  
             }        
 581  0
             return displayMaskValue;
 582  
     }
 583  
     
 584  
     public static boolean canFullyUnmaskField(String businessObjectClassName, String fieldName, KualiForm form ) {
 585  0
                     Class businessObjClass = null;
 586  
                     try{
 587  0
                             businessObjClass = Class.forName(businessObjectClassName);
 588  0
                     }catch(Exception e){
 589  0
                             throw new RuntimeException("Unable to resolve class name: " + businessObjectClassName);
 590  0
                     }
 591  0
                     if ( form instanceof KualiDocumentFormBase ) {
 592  0
                             return KNSServiceLocator.getBusinessObjectAuthorizationService().canFullyUnmaskField( GlobalVariables.getUserSession().getPerson(),
 593  
                                             businessObjClass, fieldName, ((KualiDocumentFormBase)form).getDocument() );
 594  
                     } else {
 595  0
                             return KNSServiceLocator.getBusinessObjectAuthorizationService().canFullyUnmaskField(GlobalVariables.getUserSession().getPerson(),
 596  
                                             businessObjClass, fieldName, null);
 597  
                     }
 598  
     }
 599  
     
 600  
     public static boolean canPartiallyUnmaskField(String businessObjectClassName, String fieldName, KualiForm form ) {
 601  0
             Class businessObjClass = null;
 602  
             try{
 603  0
                     businessObjClass = Class.forName(businessObjectClassName);                    
 604  0
             }catch(Exception e){
 605  0
                     throw new RuntimeException("Unable to resolve class name: " + businessObjectClassName);
 606  0
             }
 607  0
             if ( form instanceof KualiDocumentFormBase ) {
 608  0
                     return KNSServiceLocator.getBusinessObjectAuthorizationService().canPartiallyUnmaskField( GlobalVariables.getUserSession().getPerson(),
 609  
                                     businessObjClass, fieldName, ((KualiDocumentFormBase)form).getDocument() );
 610  
             } else {
 611  0
                     return KNSServiceLocator.getBusinessObjectAuthorizationService().canPartiallyUnmaskField(GlobalVariables.getUserSession().getPerson(),
 612  
                                     businessObjClass, fieldName, null);
 613  
             }
 614  
     }
 615  
     
 616  
     public static boolean canAddNoteAttachment(Document document) {
 617  0
             boolean canViewNoteAttachment = false;
 618  0
             DocumentAuthorizer documentAuthorizer = KNSServiceLocator.getDocumentHelperService().getDocumentAuthorizer(document);
 619  0
             canViewNoteAttachment = documentAuthorizer.canAddNoteAttachment(document, null, GlobalVariables.getUserSession().getPerson());
 620  0
             return canViewNoteAttachment;
 621  
     }
 622  
     
 623  
     public static boolean canViewNoteAttachment(Document document, String attachmentTypeCode) {
 624  0
             boolean canViewNoteAttachment = false;
 625  0
             DocumentAuthorizer documentAuthorizer = KNSServiceLocator.getDocumentHelperService().getDocumentAuthorizer(document);
 626  0
             canViewNoteAttachment = documentAuthorizer.canViewNoteAttachment(document, attachmentTypeCode, GlobalVariables.getUserSession().getPerson());
 627  0
             return canViewNoteAttachment;
 628  
     }
 629  
     
 630  
     public static boolean canDeleteNoteAttachment(Document document, String attachmentTypeCode, String authorUniversalIdentifier) {
 631  0
             boolean canDeleteNoteAttachment = false;
 632  0
             DocumentAuthorizer documentAuthorizer = KNSServiceLocator.getDocumentHelperService().getDocumentAuthorizer(document);
 633  0
             canDeleteNoteAttachment = documentAuthorizer.canDeleteNoteAttachment(document, attachmentTypeCode, "false", GlobalVariables.getUserSession().getPerson());
 634  0
             if(canDeleteNoteAttachment){
 635  0
                     return canDeleteNoteAttachment;
 636  
             }else{
 637  0
                     canDeleteNoteAttachment = documentAuthorizer.canDeleteNoteAttachment(document, attachmentTypeCode, "true", GlobalVariables.getUserSession().getPerson());
 638  0
                     if(canDeleteNoteAttachment && !authorUniversalIdentifier.equals(GlobalVariables.getUserSession().getPerson().getPrincipalId())){
 639  0
                             canDeleteNoteAttachment = false;
 640  
                     }
 641  
             }
 642  0
             return canDeleteNoteAttachment;
 643  
     }
 644  
     
 645  
     public static void reuseErrorMapFromPreviousRequest(KualiDocumentFormBase kualiDocumentFormBase) {
 646  0
             if (kualiDocumentFormBase.getMessageMapFromPreviousRequest() == null) {
 647  0
                     LOG.error("Error map from previous request is null!");
 648  0
                     return;
 649  
             }
 650  0
             MessageMap errorMapFromGlobalVariables = GlobalVariables.getMessageMap();
 651  0
             if (kualiDocumentFormBase.getMessageMapFromPreviousRequest() == errorMapFromGlobalVariables) {
 652  
                     // if we've switched them already, then return early and do nothing
 653  0
                     return;
 654  
             }
 655  0
             if (!errorMapFromGlobalVariables.isEmpty()) {
 656  0
                     throw new RuntimeException("Cannot replace error map because it is not empty");
 657  
             }
 658  0
             GlobalVariables.setMessageMap(kualiDocumentFormBase.getMessageMapFromPreviousRequest());
 659  0
             GlobalVariables.getMessageMap().clearErrorPath();
 660  0
     }
 661  
     
 662  
     /**
 663  
      * Excapes out HTML to prevent XSS attacks, and replaces the following strings to allow for a limited set of HTML tags
 664  
      * 
 665  
      * <li> [X] and [/X], where X represents any 1 or 2 letter string may be used to specify the equivalent tag in HTML (i.e. &lt;X&gt; and &lt;/X&gt;)
 666  
      * <li> [font COLOR], where COLOR represents any valid html color (i.e. color name or hexcode preceeded by #) will be filtered into &lt;font color="COLOR"/&gt;
 667  
      * <li> [/font] will be filtered into &lt;/font&gt;
 668  
      * <li> [table CLASS], where CLASS gives the style class to use, will be filter into &lt;table class="CLASS"/&gt;
 669  
      * <li> [/table] will be filtered into &lt;/table&gt;
 670  
      * <li> [td CLASS], where CLASS gives the style class to use, will be filter into &lt;td class="CLASS"/&gt;
 671  
      * 
 672  
      * @param inputString
 673  
      * @return
 674  
      */
 675  
     public static String filterHtmlAndReplaceRiceMarkup(String inputString) {
 676  0
             String outputString = StringEscapeUtils.escapeHtml(inputString);
 677  
             // string has been escaped of all <, >, and & (and other characters)
 678  
             
 679  0
             Map<String, String> findAndReplacePatterns = new HashMap<String, String>();
 680  
             
 681  
             // now replace our rice custom markup into html
 682  
 
 683  
             // DON'T ALLOW THE SCRIPT TAG OR ARBITRARY IMAGES/URLS/ETC. THROUGH
 684  
             
 685  
             // filter any one character tags
 686  0
             findAndReplacePatterns.put("\\[([A-Za-z])\\]", "<$1>");
 687  0
             findAndReplacePatterns.put("\\[/([A-Za-z])\\]", "</$1>");            
 688  
             // filter any two character tags
 689  0
             findAndReplacePatterns.put("\\[([A-Za-z]{2})\\]", "<$1>");
 690  0
             findAndReplacePatterns.put("\\[/([A-Za-z]{2})\\]", "</$1>");
 691  
             // filter the font tag
 692  0
             findAndReplacePatterns.put("\\[font (#[0-9A-Fa-f]{1,6}|[A-Za-z]+)\\]", "<font color=\"$1\">");
 693  0
             findAndReplacePatterns.put("\\[/font\\]", "</font>");
 694  
             // filter the table tag
 695  0
             findAndReplacePatterns.put("\\[table\\]", "<table>");
 696  0
             findAndReplacePatterns.put("\\[table ([A-Za-z]+)\\]", "<table class=\"$1\">");
 697  0
             findAndReplacePatterns.put("\\[/table\\]", "</table>");
 698  
             // fiter td with class
 699  0
             findAndReplacePatterns.put("\\[td ([A-Za-z]+)\\]", "<td class=\"$1\">");
 700  
             
 701  0
             for (String findPattern : findAndReplacePatterns.keySet()) {
 702  0
                     Pattern p = Pattern.compile(findPattern);
 703  0
                     Matcher m = p.matcher(outputString);
 704  0
                     if (m.find()) {
 705  0
                             String replacePattern = findAndReplacePatterns.get(findPattern);
 706  0
                             outputString = m.replaceAll(replacePattern);
 707  
                     }
 708  0
             }
 709  
             
 710  0
             return outputString;
 711  
     }
 712  
     
 713  
     public static boolean containsSensitiveDataPatternMatch(String fieldValue) {
 714  0
             if (StringUtils.isBlank(fieldValue)) {
 715  0
                     return false;
 716  
             }
 717  0
             ParameterService parameterService = KNSServiceLocator.getParameterService();
 718  0
             List<String> sensitiveDataPatterns = parameterService.getParameterValues(KNSConstants.KNS_NAMESPACE, ParameterConstants.ALL_COMPONENT, 
 719  
                             KNSConstants.SystemGroupParameterNames.SENSITIVE_DATA_PATTERNS);
 720  0
             for (String pattern : sensitiveDataPatterns){
 721  0
                     if (Pattern.compile(pattern).matcher(fieldValue).find()) {
 722  0
                             return true;
 723  
                     }
 724  
             }
 725  0
             return false;
 726  
     }
 727  
     
 728  
     /**
 729  
      * Determines and returns the URL for question button images; looks first for a property "application.custom.image.url", 
 730  
      * and if that is missing, uses the image url returned by getDefaultButtonImageUrl()
 731  
      * @param imageName the name of the image to find a button for
 732  
      * @return the URL where question button images are located
 733  
      */
 734  
     public static String getButtonImageUrl(String imageName) {
 735  0
             String buttonImageUrl = getKualiConfigurationService().getPropertyString(WebUtils.APPLICATION_IMAGE_URL_PROPERTY_PREFIX+"."+imageName);
 736  0
             if (StringUtils.isBlank(buttonImageUrl)) {
 737  0
                     buttonImageUrl = getDefaultButtonImageUrl(imageName);
 738  
             }
 739  0
             return buttonImageUrl;
 740  
     }
 741  
 
 742  
     /**
 743  
      * Generates a default button image URL, in the form of: ${kr.externalizable.images.url}buttonsmall_${imageName}.gif
 744  
      * 
 745  
      * @param imageName the image name to generate a default button name for
 746  
      * @return the default button image url
 747  
      */
 748  
     public static String getDefaultButtonImageUrl(String imageName) {
 749  0
             return getKualiConfigurationService().getPropertyString(WebUtils.DEFAULT_IMAGE_URL_PROPERTY_NAME)+"buttonsmall_"+imageName+".gif";
 750  
     }
 751  
     
 752  
     /**
 753  
      * @return whether the deploy environment is production
 754  
      */
 755  
     public static boolean isProductionEnvironment(){
 756  0
             return getKualiConfigurationService().isProductionEnvironment();
 757  
     }
 758  
     
 759  
     /**
 760  
      * @return an implementation of the KualiConfigurationService
 761  
      */
 762  
     public static KualiConfigurationService getKualiConfigurationService() {
 763  0
             if (configurationService == null) {
 764  0
                     configurationService = KNSServiceLocator.getKualiConfigurationService();
 765  
             }
 766  0
             return configurationService;
 767  
     }
 768  
 }