001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/security/owsrequestvalidator/wms/GetFeatureInfoRequestValidator.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 package org.deegree.security.owsrequestvalidator.wms; 037 038 import static org.deegree.security.drm.model.RightType.GETFEATUREINFO; 039 040 import java.util.List; 041 042 import org.deegree.datatypes.QualifiedName; 043 import org.deegree.datatypes.Types; 044 import org.deegree.model.feature.Feature; 045 import org.deegree.model.feature.FeatureFactory; 046 import org.deegree.model.feature.FeatureProperty; 047 import org.deegree.model.feature.schema.FeatureType; 048 import org.deegree.model.feature.schema.PropertyType; 049 import org.deegree.ogcwebservices.InvalidParameterValueException; 050 import org.deegree.ogcwebservices.OGCWebServiceRequest; 051 import org.deegree.ogcwebservices.wms.operation.GetFeatureInfo; 052 import org.deegree.ogcwebservices.wms.operation.GetMap; 053 import org.deegree.security.UnauthorizedException; 054 import org.deegree.security.drm.model.User; 055 import org.deegree.security.owsproxy.Condition; 056 import org.deegree.security.owsproxy.OperationParameter; 057 import org.deegree.security.owsproxy.Request; 058 import org.deegree.security.owsrequestvalidator.Messages; 059 import org.deegree.security.owsrequestvalidator.Policy; 060 import org.deegree.security.owsrequestvalidator.RequestValidator; 061 062 /** 063 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a> 064 * @author last edited by: $Author: mschneider $ 065 * 066 * @version 1.1, $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18 Jun 2009) $ 067 * 068 * @since 1.1 069 */ 070 071 class GetFeatureInfoRequestValidator extends RequestValidator { 072 073 // known condition parameter 074 private static final String INFOLAYERS = "featureInfoLayers"; 075 076 private static final String INFOFORMAT = "infoFormat"; 077 078 private static final String FEATURECOUNT = "maxFeatureCount"; 079 080 private static final String INVALIDCLICKPOINT = Messages.getString( "GetFeatureInfoRequestValidator.INVALIDCLICKPOINT" ); 081 082 private static final String INVALIDLAYER = Messages.getString( "GetFeatureInfoRequestValidator.INVALIDLAYER" ); 083 084 private static final String INVALIDFORMAT = Messages.getString( "GetFeatureInfoRequestValidator.INVALIDFORMAT" ); 085 086 private static final String INAVLIDFEATURECOUNT = Messages.getString( "GetFeatureInfoRequestValidator.INAVLIDFEATURECOUNT" ); 087 088 private static FeatureType gfiFT = null; 089 090 static { 091 if ( gfiFT == null ) { 092 gfiFT = GetFeatureInfoRequestValidator.createFeatureType(); 093 } 094 } 095 096 /** 097 * @param policy 098 */ 099 public GetFeatureInfoRequestValidator( Policy policy ) { 100 super( policy ); 101 } 102 103 /** 104 * validates the incoming GetFeatureInfo request against the policy assigned to a validator 105 * 106 * @param request 107 * request to validate 108 * @param user 109 * name of the user who likes to perform the request (can be null) 110 */ 111 @Override 112 public void validateRequest( OGCWebServiceRequest request, User user ) 113 throws InvalidParameterValueException, UnauthorizedException { 114 115 userCoupled = false; 116 Request req = policy.getRequest( "WMS", "GetFeatureInfo" ); 117 // request is valid because no restrictions are made 118 if ( req.isAny() || req.getPreConditions().isAny() ) { 119 return; 120 } 121 Condition condition = req.getPreConditions(); 122 123 GetFeatureInfo wmsreq = (GetFeatureInfo) request; 124 125 // validate the GetMap request contained in the 126 // GetFeatureInfo request 127 GetMapRequestValidator gmrv = new GetMapRequestValidator( policy ); 128 GetMap gmr = wmsreq.getGetMapRequestCopy(); 129 gmrv.validateRequest( gmr, user ); 130 131 validateXY( gmr, wmsreq ); 132 validateInfoLayers( condition, wmsreq.getQueryLayers() ); 133 validateInfoFormat( condition, wmsreq.getInfoFormat() ); 134 validateFeatureCount( condition, wmsreq.getFeatureCount() ); 135 136 if ( userCoupled ) { 137 validateAgainstRightsDB( wmsreq, user ); 138 } 139 140 } 141 142 /** 143 * validates the click point (x,y coordinate) to be located within the map image that has been base of the 144 * GetFeatureInfo request 145 * 146 * @param gmr 147 * @param gfir 148 * @throws InvalidParameterValueException 149 */ 150 private void validateXY( GetMap gmr, GetFeatureInfo gfir ) 151 throws InvalidParameterValueException { 152 153 int x = gfir.getClickPoint().x; 154 int y = gfir.getClickPoint().y; 155 156 int width = gmr.getWidth(); 157 int height = gmr.getHeight(); 158 159 if ( x < 0 || x >= width || y < 0 || y >= height ) { 160 throw new InvalidParameterValueException( INVALIDCLICKPOINT ); 161 } 162 163 } 164 165 /** 166 * validates if the requested info layers layers are valid against the policy/condition. If the passed user <>null 167 * this is checked against the user- and rights-management system/repository 168 * 169 * @param condition 170 * @param layers 171 * @throws InvalidParameterValueException 172 */ 173 private void validateInfoLayers( Condition condition, String[] layers ) 174 throws InvalidParameterValueException { 175 176 OperationParameter op = condition.getOperationParameter( INFOLAYERS ); 177 178 // version is valid because no restrictions are made 179 if ( op.isAny() ) 180 return; 181 182 List<String> validLayers = op.getValues(); 183 if ( op.isUserCoupled() ) { 184 userCoupled = true; 185 } else { 186 for ( int i = 0; i < layers.length; i++ ) { 187 if ( !validLayers.contains( layers[i] ) ) { 188 throw new InvalidParameterValueException( INVALIDLAYER + layers[i] ); 189 } 190 } 191 } 192 } 193 194 /** 195 * checks if the passed format is valid against the format defined in the policy. If <tt>user</ff> != <tt>null</tt> 196 * format will be compared against the user/rights repository 197 * 198 * @param condition 199 * condition containing the definition of the valid format 200 * @param format 201 * @throws InvalidParameterValueException 202 */ 203 private void validateInfoFormat( Condition condition, String format ) 204 throws InvalidParameterValueException { 205 206 OperationParameter op = condition.getOperationParameter( INFOFORMAT ); 207 208 // version is valid because no restrictions are made 209 if ( op.isAny() ) { 210 return; 211 } 212 213 List<String> list = op.getValues(); 214 if ( op.isUserCoupled() ) { 215 userCoupled = true; 216 } else { 217 if ( !list.contains( format ) ) { 218 throw new InvalidParameterValueException( INVALIDFORMAT + format ); 219 } 220 } 221 222 } 223 224 /** 225 * checks if the passed featureCount is valid against the featureCount defined in the policy and if it is greater 226 * zero. If <tt>user</ff> != <tt>null</tt> featureCount will be compared against the user/rights repository 227 * 228 * @param condition 229 * @param featureCount 230 * @throws InvalidParameterValueException 231 */ 232 private void validateFeatureCount( Condition condition, int featureCount ) 233 throws InvalidParameterValueException { 234 235 OperationParameter op = condition.getOperationParameter( FEATURECOUNT ); 236 237 // version is valid because no restrictions are made 238 if ( op.isAny() ) 239 return; 240 241 if ( op.isUserCoupled() ) { 242 userCoupled = true; 243 } else { 244 if ( featureCount < 1 || featureCount > op.getFirstAsInt() ) { 245 throw new InvalidParameterValueException( INAVLIDFEATURECOUNT + featureCount ); 246 } 247 } 248 } 249 250 /** 251 * validates the passed WMS GetMap request against a User- and Rights-Management DB. 252 * 253 * @param wmsreq 254 * @param user 255 * @throws InvalidParameterValueException 256 */ 257 private void validateAgainstRightsDB( GetFeatureInfo wmsreq, User user ) 258 throws InvalidParameterValueException, UnauthorizedException { 259 260 if ( user == null ) { 261 throw new UnauthorizedException( "no access to anonymous user" ); 262 } 263 264 // create feature that describes the map request 265 FeatureProperty[] fps = new FeatureProperty[6]; 266 fps[0] = FeatureFactory.createFeatureProperty( new QualifiedName( "version" ), wmsreq.getVersion() ); 267 Integer x = new Integer( wmsreq.getClickPoint().x ); 268 fps[1] = FeatureFactory.createFeatureProperty( new QualifiedName( "x" ), x ); 269 Integer y = new Integer( wmsreq.getClickPoint().y ); 270 fps[2] = FeatureFactory.createFeatureProperty( new QualifiedName( "y" ), y ); 271 fps[3] = FeatureFactory.createFeatureProperty( new QualifiedName( "infoformat" ), wmsreq.getInfoFormat() ); 272 fps[4] = FeatureFactory.createFeatureProperty( new QualifiedName( "exceptions" ), wmsreq.getExceptions() ); 273 Integer fc = new Integer( wmsreq.getFeatureCount() ); 274 fps[5] = FeatureFactory.createFeatureProperty( new QualifiedName( "featurecount" ), fc ); 275 276 Feature feature = FeatureFactory.createFeature( "id", gfiFT, fps ); 277 String[] layer = wmsreq.getQueryLayers(); 278 for ( int i = 0; i < layer.length; i++ ) { 279 if ( securityConfig.getProxiedUrl() == null ) { 280 handleUserCoupledRules( user, feature, layer[i], "Layer", GETFEATUREINFO ); 281 } else { 282 handleUserCoupledRules( user, feature, "[" + securityConfig.getProxiedUrl() + "]:" + layer[i], "Layer", 283 GETFEATUREINFO ); 284 } 285 } 286 } 287 288 private static FeatureType createFeatureType() { 289 PropertyType[] ftps = new PropertyType[6]; 290 ftps[0] = FeatureFactory.createSimplePropertyType( new QualifiedName( "version" ), Types.INTEGER, false ); 291 ftps[1] = FeatureFactory.createSimplePropertyType( new QualifiedName( "x" ), Types.INTEGER, false ); 292 ftps[2] = FeatureFactory.createSimplePropertyType( new QualifiedName( "y" ), Types.INTEGER, false ); 293 ftps[3] = FeatureFactory.createSimplePropertyType( new QualifiedName( "infoformat" ), Types.VARCHAR, false ); 294 ftps[4] = FeatureFactory.createSimplePropertyType( new QualifiedName( "exceptions" ), Types.VARCHAR, false ); 295 ftps[5] = FeatureFactory.createSimplePropertyType( new QualifiedName( "featurecount" ), Types.INTEGER, false ); 296 297 return FeatureFactory.createFeatureType( "GetFeatureInfo", false, ftps ); 298 } 299 300 }