001/* 002 * (C) Copyright 2006-2007 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> 018 * 019 * $Id: InputFileMimetypeValidator.java 28610 2008-01-09 17:13:52Z sfermigier $ 020 */ 021 022package org.nuxeo.ecm.platform.ui.web.component.file; 023 024import javax.faces.component.StateHolder; 025import javax.faces.component.UIComponent; 026import javax.faces.context.FacesContext; 027import javax.faces.validator.Validator; 028import javax.faces.validator.ValidatorException; 029 030import org.apache.commons.lang.StringUtils; 031import org.apache.commons.logging.Log; 032import org.apache.commons.logging.LogFactory; 033 034import com.sun.faces.util.MessageFactory; 035 036/** 037 * Input file mimetype validator. 038 * <p> 039 * Validates an {@link InputFileInfo} blob value in case it's been uploaded. Accepted mimetypes are set using the 040 * "extensions" attribute, representing the list of accepted extension suffixes separated by commas (for instance: 041 * ".jpeg, .png"). 042 * <p> 043 * Validation is done on the filename, no actual mimetype check is done for now. 044 * 045 * @author <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> 046 */ 047public class InputFileMimetypeValidator implements Validator, StateHolder { 048 049 public static final String VALIDATOR_ID = "InputFileMimetypeValidator"; 050 051 @SuppressWarnings("unused") 052 private static final Log log = LogFactory.getLog(InputFileSizeValidator.class); 053 054 private String[] extensions; 055 056 private boolean authorized = true; 057 058 private boolean hidden = false; 059 060 private boolean transientValue = false; 061 062 /** 063 * The message identifier of the {@link javax.faces.application.FacesMessage} to be created if the authorized 064 * extensions check fails. The message format string for this message may optionally include the following 065 * placeholders: 066 * <ul> 067 * <li><code>{0}</code> replaced by the configured auhtorized extensions.</li> 068 * </ul> 069 * </p> 070 */ 071 public static final String MIMETYPE_AUTHORIZED_EXTENSIONS_MESSAGE_ID = "error.inputFile.authorizedExtensions"; 072 073 /** 074 * The message identifier of the {@link javax.faces.application.FacesMessage} to be created if the unauthorized 075 * extensions check fails. The message format string for this message may optionally include the following 076 * placeholders: 077 * <ul> 078 * <li><code>{0}</code> replaced by the configured unauthorized extensions.</li> 079 * </ul> 080 * </p> 081 */ 082 public static final String MIMETYPE_UNAUTHORIZED_EXTENSIONS_MESSAGE_ID = "error.inputFile.unauthorizedExtensions"; 083 084 @Override 085 public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException { 086 if (value != null && extensions != null && extensions.length > 0) { 087 if (value instanceof InputFileInfo) { 088 InputFileInfo info = (InputFileInfo) value; 089 String choice = info.getConvertedChoice(); 090 if (!InputFileChoice.isUploadOrKeepTemp(choice)) { 091 return; 092 } 093 String filename = info.getConvertedFilename(); 094 if (filename != null) { 095 String lowerCaseFilename = filename.toLowerCase(); 096 boolean error = authorized; 097 for (String extension : extensions) { 098 String lowerCaseExtension = extension.trim().toLowerCase(); 099 if (lowerCaseFilename.endsWith(lowerCaseExtension)) { 100 error = !authorized; 101 break; 102 } 103 } 104 // TODO: handle content types 105 if (error) { 106 String messageId = authorized ? MIMETYPE_AUTHORIZED_EXTENSIONS_MESSAGE_ID 107 : MIMETYPE_UNAUTHORIZED_EXTENSIONS_MESSAGE_ID; 108 throw new ValidatorException(MessageFactory.getMessage(context, messageId, 109 StringUtils.join(extensions, ", "))); 110 } 111 } 112 } 113 } 114 } 115 116 public String[] getExtensions() { 117 return extensions; 118 } 119 120 public void setExtensions(String[] extensions) { 121 this.extensions = extensions; 122 } 123 124 public boolean isAuthorized() { 125 return authorized; 126 } 127 128 public void setAuthorized(boolean authorized) { 129 this.authorized = authorized; 130 } 131 132 public boolean isHidden() { 133 return hidden; 134 } 135 136 public void setHidden(boolean hidden) { 137 this.hidden = hidden; 138 } 139 140 @Override 141 public boolean isTransient() { 142 return transientValue; 143 } 144 145 @Override 146 public void setTransient(boolean newTransientValue) { 147 transientValue = newTransientValue; 148 } 149 150 @Override 151 public Object saveState(FacesContext context) { 152 Object[] values = new Object[3]; 153 values[0] = extensions; 154 values[1] = authorized; 155 values[2] = hidden; 156 return values; 157 } 158 159 @Override 160 public void restoreState(FacesContext context, Object state) { 161 Object[] values = (Object[]) state; 162 extensions = (String[]) values[0]; 163 authorized = ((Boolean) values[1]).booleanValue(); 164 hidden = ((Boolean) values[2]).booleanValue(); 165 } 166 167}