Add unit tests for WMS server access control with request filters

This commit is contained in:
Nyall Dawson 2016-02-23 11:47:18 +11:00
parent c23e3096fe
commit ab73c0364c
2 changed files with 492 additions and 11 deletions

View File

@ -107,6 +107,8 @@ class RestrictedAccessControl(QgsAccessControlFilter):
return "pk = 1"
elif layer.name() == "Hello_Project_SubsetString":
return "pkuid = 6 or pkuid = 7"
elif layer.name() == "Hello_Filter_SubsetString":
return "pkuid = 6 or pkuid = 7"
else:
return None
@ -866,6 +868,47 @@ class TestQgsServerAccessControl(unittest.TestCase):
response, headers = self._get_restricted(query_string)
self._img_diff_error(response, headers, "Restricted_WMS_GetMap")
def test_wms_getmap_subsetstring_with_filter(self):
""" test that request filter and access control subsetStrings are correctly combined. Note that for this
test we reuse the projectsubsetstring reference images as we are using filter requests to set the same
filter " pkuid in (7,8) " as the project subsetstring uses for its test.
"""
query_string = "&".join(["%s=%s" % i for i in {
"MAP": urllib.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetMap",
"LAYERS": "Hello_Filter_SubsetString",
"FILTER": "Hello_Filter_SubsetString:\"pkuid\" IN ( 7 , 8 )",
"STYLES": "",
"FORMAT": "image/png",
"BBOX": "-16817707,-4710778,5696513,14587125",
"HEIGHT": "500",
"WIDTH": "500",
"SRS": "EPSG:3857"
}.items()])
response, headers = self._get_fullaccess(query_string)
self._img_diff_error(response, headers, "WMS_GetMap_projectsubstring")
query_string = "&".join(["%s=%s" % i for i in {
"MAP": urllib.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetMap",
"LAYERS": "Hello_Filter_SubsetString",
"FILTER": "Hello_Filter_SubsetString:\"pkuid\" IN ( 7 , 8 )",
"STYLES": "",
"FORMAT": "image/png",
"BBOX": "-16817707,-4710778,5696513,14587125",
"HEIGHT": "500",
"WIDTH": "500",
"SRS": "EPSG:3857"
}.items()])
response, headers = self._get_restricted(query_string)
self._img_diff_error(response, headers, "Restricted_WMS_GetMap_projectsubstring")
def test_wms_getmap_projectsubsetstring(self):
""" test that project set layer subsetStrings are honored"""
query_string = "&".join(["%s=%s" % i for i in {
@ -1005,7 +1048,7 @@ class TestQgsServerAccessControl(unittest.TestCase):
"Project set layer subsetString not honored in WMS GetFeatureInfo when access control applied/1\n%s" % response)
def test_wms_getfeatureinfo_projectsubsetstring2(self):
"""test that layer subsetStrings set in projects are honored. This test checks for a feature which should be pass
"""test that layer subsetStrings set in projects are honored. This test checks for a feature which should pass
both project set layer subsetString and access control filters
"""
query_string = "&".join(["%s=%s" % i for i in {
@ -1043,8 +1086,8 @@ class TestQgsServerAccessControl(unittest.TestCase):
str(response).find("<qgs:pk>7</qgs:pk>") != -1,
"No good result result in GetFeatureInfo Hello/2\n%s" % response)
def test_wms_getfeatureinfo_projectsubsetstring2(self):
"""test that layer subsetStrings set in projects are honored. This test checks for a feature which should be pass
def test_wms_getfeatureinfo_projectsubsetstring3(self):
"""test that layer subsetStrings set in projects are honored. This test checks for a feature which should pass
the project set layer subsetString but fail the access control checks
"""
query_string = "&".join(["%s=%s" % i for i in {
@ -1079,6 +1122,117 @@ class TestQgsServerAccessControl(unittest.TestCase):
str(response).find("<qgs:pk>") != -1,
"Unexpected result from GetFeatureInfo Hello/2\n%s" % response)
def test_wms_getfeatureinfo_subsetstring_with_filter(self):
"""test that request filters are honored. This test checks for a feature which should be filtered
out by the request filter
"""
query_string = "&".join(["%s=%s" % i for i in {
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetFeatureInfo",
"LAYERS": "Hello_Filter_SubsetString",
"QUERY_LAYERS": "Hello_Filter_SubsetString",
"FILTER": "Hello_Filter_SubsetString:\"pkuid\" IN ( 7 , 8 )",
"STYLES": "",
"FORMAT": "image/png",
"BBOX": "-16817707,-4710778,5696513,14587125",
"HEIGHT": "500",
"WIDTH": "500",
"SRS": "EPSG:3857",
"FEATURE_COUNT": "10",
"INFO_FORMAT": "application/vnd.ogc.gml",
"X": "56",
"Y": "144",
"MAP": urllib.quote(self.projectPath)
}.items()])
response, headers = self._get_fullaccess(query_string)
self.assertFalse(
str(response).find("<qgs:pk>") != -1,
"Request filter not honored in WMS GetFeatureInfo/1\n%s" % response)
response, headers = self._get_restricted(query_string)
self.assertFalse(
str(response).find("<qgs:pk>") != -1,
"Request filter not honored in WMS GetFeatureInfo when access control applied/1\n%s" % response)
def test_wms_getfeatureinfo_projectsubsetstring2(self):
"""test that request filters are honored. This test checks for a feature which should pass
both request filter and access control filters
"""
query_string = "&".join(["%s=%s" % i for i in {
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetFeatureInfo",
"LAYERS": "Hello_Filter_SubsetString",
"QUERY_LAYERS": "Hello_Filter_SubsetString",
"FILTER": "Hello_Filter_SubsetString:\"pkuid\" IN ( 7 , 8 )",
"STYLES": "",
"FORMAT": "image/png",
"BBOX": "-1623412,3146330,-1603412,3166330",
"HEIGHT": "500",
"WIDTH": "500",
"SRS": "EPSG:3857",
"FEATURE_COUNT": "10",
"INFO_FORMAT": "application/vnd.ogc.gml",
"X": "146",
"Y": "160",
"MAP": urllib.quote(self.projectPath)
}.items()])
response, headers = self._get_fullaccess(query_string)
self.assertTrue(
str(response).find("<qgs:pk>") != -1,
"No result result in GetFeatureInfo Hello/2\n%s" % response)
self.assertTrue(
str(response).find("<qgs:pk>7</qgs:pk>") != -1,
"No good result result in GetFeatureInfo Hello/2\n%s" % response)
response, headers = self._get_restricted(query_string)
self.assertTrue(
str(response).find("<qgs:pk>") != -1,
"No result result in GetFeatureInfo Hello/2\n%s" % response)
self.assertTrue(
str(response).find("<qgs:pk>7</qgs:pk>") != -1,
"No good result result in GetFeatureInfo Hello/2\n%s" % response)
def test_wms_getfeatureinfo_projectsubsetstring3(self):
"""test that request filters are honored. This test checks for a feature which should pass
the request filter but fail the access control checks
"""
query_string = "&".join(["%s=%s" % i for i in {
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetFeatureInfo",
"LAYERS": "Hello_Filter_SubsetString",
"QUERY_LAYERS": "Hello_Filter_SubsetString",
"FILTER": "Hello_Filter_SubsetString:\"pkuid\" IN ( 7 , 8 )",
"STYLES": "",
"FORMAT": "image/png",
"BBOX": "3415650,2018968,3415750,2019968",
"HEIGHT": "500",
"WIDTH": "500",
"SRS": "EPSG:3857",
"FEATURE_COUNT": "10",
"INFO_FORMAT": "application/vnd.ogc.gml",
"X": "146",
"Y": "160",
"MAP": urllib.quote(self.projectPath)
}.items()])
response, headers = self._get_fullaccess(query_string)
self.assertTrue(
str(response).find("<qgs:pk>") != -1,
"No result result in GetFeatureInfo Hello/2\n%s" % response)
self.assertTrue(
str(response).find("<qgs:pk>8</qgs:pk>") != -1,
"No good result result in GetFeatureInfo Hello/2\n%s" % response)
response, headers = self._get_restricted(query_string)
self.assertFalse(
str(response).find("<qgs:pk>") != -1,
"Unexpected result from GetFeatureInfo Hello/2\n%s" % response)
# # WFS # # WFS # # WFS # #
def test_wfs_getfeature_subsetstring(self):

View File

@ -15,6 +15,9 @@
<layer-tree-layer expanded="1" checked="Qt::Checked" id="Hello_SubsetString_copy20160222085231770" name="Hello_Project_SubsetString">
<customproperties/>
</layer-tree-layer>
<layer-tree-layer expanded="1" checked="Qt::Checked" id="Hello_Project_SubsetString_copy20160223113949592" name="Hello_Filter_SubsetString">
<customproperties/>
</layer-tree-layer>
<layer-tree-layer expanded="0" checked="Qt::Checked" id="dem20150730091219559" name="dem">
<customproperties/>
</layer-tree-layer>
@ -26,10 +29,10 @@
<mapcanvas>
<units>meters</units>
<extent>
<xmin>-18850007.98058429732918739</xmin>
<ymin>-15457772.87261204048991203</ymin>
<xmax>19663195.48641690239310265</xmax>
<ymax>23138032.31389476731419563</ymax>
<xmin>-15398461.32893919758498669</xmin>
<ymin>-387737.65663182735443115</ymin>
<xmax>11994411.33100509829819202</xmax>
<ymax>11190075.94268352724611759</ymax>
</extent>
<rotation>0</rotation>
<projections>1</projections>
@ -55,6 +58,7 @@
<layer_coordinate_transform destAuthId="EPSG:3857" srcAuthId="EPSG:3857" srcDatumTransform="-1" destDatumTransform="-1" layerid="points20150803121107046"/>
<layer_coordinate_transform destAuthId="EPSG:3857" srcAuthId="EPSG:3857" srcDatumTransform="-1" destDatumTransform="-1" layerid="Hello20150522142526972"/>
<layer_coordinate_transform destAuthId="EPSG:3857" srcAuthId="EPSG:3857" srcDatumTransform="-1" destDatumTransform="-1" layerid="landsat20150522140814516"/>
<layer_coordinate_transform destAuthId="EPSG:3857" srcAuthId="EPSG:3857" srcDatumTransform="-1" destDatumTransform="-1" layerid="Hello_Project_SubsetString_copy20160223113949592"/>
</layer_coordinate_transform_info>
</mapcanvas>
<layer-tree-canvas>
@ -65,6 +69,7 @@
<item>points20150803121107046</item>
<item>Hello_copy20150804164427541</item>
<item>Hello_SubsetString_copy20160222085231770</item>
<item>Hello_Project_SubsetString_copy20160223113949592</item>
</custom-order>
</layer-tree-canvas>
<legend updateDrawingOrder="true">
@ -88,6 +93,11 @@
<legendlayerfile isInOverview="0" layerid="Hello_SubsetString_copy20160222085231770" visible="1"/>
</filegroup>
</legendlayer>
<legendlayer drawingOrder="-1" open="true" checked="Qt::Checked" name="Hello_Filter_SubsetString" showFeatureCount="0">
<filegroup open="true" hidden="false">
<legendlayerfile isInOverview="0" layerid="Hello_Project_SubsetString_copy20160223113949592" visible="1"/>
</filegroup>
</legendlayer>
<legendlayer drawingOrder="-1" open="false" checked="Qt::Checked" name="dem" showFeatureCount="0">
<filegroup open="false" hidden="false">
<legendlayerfile isInOverview="0" layerid="dem20150730091219559" visible="1"/>
@ -205,6 +215,323 @@
</Composition>
</Composer>
<projectlayers>
<maplayer minimumScale="0" maximumScale="1e+08" simplifyDrawingHints="1" minLabelScale="1" maxLabelScale="1e+08" simplifyDrawingTol="1" geometry="Polygon" simplifyMaxScale="1" type="vector" hasScaleBasedVisibilityFlag="0" simplifyLocal="1" scaleBasedLabelVisibilityFlag="0">
<id>Hello_Project_SubsetString_copy20160223113949592</id>
<datasource>dbname='./helloworld.db' table="hello" (geom) sql=</datasource>
<shortname></shortname>
<title></title>
<abstract></abstract>
<keywordList>
<value></value>
</keywordList>
<layername>Hello_Filter_SubsetString</layername>
<srs>
<spatialrefsys>
<proj4>+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs</proj4>
<srsid>3857</srsid>
<srid>3857</srid>
<authid>EPSG:3857</authid>
<description>WGS 84 / Pseudo Mercator</description>
<projectionacronym>merc</projectionacronym>
<ellipsoidacronym>WGS84</ellipsoidacronym>
<geographicflag>false</geographicflag>
</spatialrefsys>
</srs>
<provider encoding="UTF-8">spatialite</provider>
<previewExpression></previewExpression>
<vectorjoins/>
<layerDependencies/>
<expressionfields/>
<map-layer-style-manager current="">
<map-layer-style name=""/>
</map-layer-style-manager>
<edittypes>
<edittype widgetv2type="TextEdit" name="pk">
<widgetv2config IsMultiline="0" fieldEditable="1" UseHtml="0" labelOnTop="1"/>
</edittype>
<edittype widgetv2type="TextEdit" name="pkuid">
<widgetv2config IsMultiline="0" fieldEditable="1" UseHtml="0" labelOnTop="0"/>
</edittype>
<edittype widgetv2type="TextEdit" name="colour">
<widgetv2config IsMultiline="0" fieldEditable="1" UseHtml="0" labelOnTop="1"/>
</edittype>
</edittypes>
<renderer-v2 forceraster="0" symbollevels="0" type="singleSymbol" enableorderby="0">
<symbols>
<symbol alpha="1" clip_to_extent="1" type="fill" name="0">
<layer pass="0" class="SimpleFill" locked="0">
<prop k="border_width_map_unit_scale" v="0,0,0,0,0,0"/>
<prop k="color" v="178,178,178,255"/>
<prop k="joinstyle" v="bevel"/>
<prop k="offset" v="0.8,0.8"/>
<prop k="offset_map_unit_scale" v="0,0,0,0,0,0"/>
<prop k="offset_unit" v="MM"/>
<prop k="outline_color" v="121,121,121,255"/>
<prop k="outline_style" v="solid"/>
<prop k="outline_width" v="0.26"/>
<prop k="outline_width_unit" v="MM"/>
<prop k="style" v="solid"/>
</layer>
<layer pass="0" class="SimpleFill" locked="0">
<prop k="border_width_map_unit_scale" v="0,0,0,0,0,0"/>
<prop k="color" v="230,85,192,255"/>
<prop k="joinstyle" v="bevel"/>
<prop k="offset" v="0,0"/>
<prop k="offset_map_unit_scale" v="0,0,0,0,0,0"/>
<prop k="offset_unit" v="MM"/>
<prop k="outline_color" v="0,0,0,255"/>
<prop k="outline_style" v="solid"/>
<prop k="outline_width" v="0.26"/>
<prop k="outline_width_unit" v="MM"/>
<prop k="style" v="solid"/>
</layer>
</symbol>
</symbols>
<rotation/>
<sizescale scalemethod="diameter"/>
</renderer-v2>
<labeling type="simple"/>
<customproperties>
<property key="labeling" value="pal"/>
<property key="labeling/addDirectionSymbol" value="false"/>
<property key="labeling/angleOffset" value="0"/>
<property key="labeling/blendMode" value="0"/>
<property key="labeling/bufferBlendMode" value="0"/>
<property key="labeling/bufferColorA" value="255"/>
<property key="labeling/bufferColorB" value="255"/>
<property key="labeling/bufferColorG" value="255"/>
<property key="labeling/bufferColorR" value="255"/>
<property key="labeling/bufferDraw" value="false"/>
<property key="labeling/bufferJoinStyle" value="64"/>
<property key="labeling/bufferNoFill" value="false"/>
<property key="labeling/bufferSize" value="1"/>
<property key="labeling/bufferSizeInMapUnits" value="false"/>
<property key="labeling/bufferSizeMapUnitMaxScale" value="0"/>
<property key="labeling/bufferSizeMapUnitMinScale" value="0"/>
<property key="labeling/bufferTransp" value="0"/>
<property key="labeling/centroidInside" value="false"/>
<property key="labeling/centroidWhole" value="false"/>
<property key="labeling/decimals" value="3"/>
<property key="labeling/displayAll" value="false"/>
<property key="labeling/dist" value="0"/>
<property key="labeling/distInMapUnits" value="false"/>
<property key="labeling/distMapUnitMaxScale" value="0"/>
<property key="labeling/distMapUnitMinScale" value="0"/>
<property key="labeling/drawLabels" value="false"/>
<property key="labeling/enabled" value="false"/>
<property key="labeling/fieldName" value="if (1 = $id, 'First', 'Others')&#xa;"/>
<property key="labeling/fitInPolygonOnly" value="false"/>
<property key="labeling/fontBold" value="false"/>
<property key="labeling/fontCapitals" value="0"/>
<property key="labeling/fontFamily" value="Sans Serif"/>
<property key="labeling/fontItalic" value="false"/>
<property key="labeling/fontLetterSpacing" value="0"/>
<property key="labeling/fontLimitPixelSize" value="false"/>
<property key="labeling/fontMaxPixelSize" value="10000"/>
<property key="labeling/fontMinPixelSize" value="3"/>
<property key="labeling/fontSize" value="9"/>
<property key="labeling/fontSizeInMapUnits" value="false"/>
<property key="labeling/fontSizeMapUnitMaxScale" value="0"/>
<property key="labeling/fontSizeMapUnitMinScale" value="0"/>
<property key="labeling/fontStrikeout" value="false"/>
<property key="labeling/fontUnderline" value="false"/>
<property key="labeling/fontWeight" value="50"/>
<property key="labeling/fontWordSpacing" value="0"/>
<property key="labeling/formatNumbers" value="false"/>
<property key="labeling/isExpression" value="true"/>
<property key="labeling/labelOffsetInMapUnits" value="true"/>
<property key="labeling/labelOffsetMapUnitMaxScale" value="0"/>
<property key="labeling/labelOffsetMapUnitMinScale" value="0"/>
<property key="labeling/labelPerPart" value="false"/>
<property key="labeling/leftDirectionSymbol" value="&lt;"/>
<property key="labeling/limitNumLabels" value="false"/>
<property key="labeling/maxCurvedCharAngleIn" value="20"/>
<property key="labeling/maxCurvedCharAngleOut" value="-20"/>
<property key="labeling/maxNumLabels" value="2000"/>
<property key="labeling/mergeLines" value="false"/>
<property key="labeling/minFeatureSize" value="0"/>
<property key="labeling/multilineAlign" value="0"/>
<property key="labeling/multilineHeight" value="1"/>
<property key="labeling/namedStyle" value="Normal"/>
<property key="labeling/obstacle" value="true"/>
<property key="labeling/obstacleFactor" value="1"/>
<property key="labeling/obstacleType" value="0"/>
<property key="labeling/offsetType" value="0"/>
<property key="labeling/placeDirectionSymbol" value="0"/>
<property key="labeling/placement" value="0"/>
<property key="labeling/placementFlags" value="0"/>
<property key="labeling/plussign" value="false"/>
<property key="labeling/predefinedPositionOrder" value="TR,TL,BR,BL,R,L,TSR,BSR"/>
<property key="labeling/preserveRotation" value="true"/>
<property key="labeling/previewBkgrdColor" value="#ffffff"/>
<property key="labeling/priority" value="5"/>
<property key="labeling/quadOffset" value="4"/>
<property key="labeling/repeatDistance" value="0"/>
<property key="labeling/repeatDistanceMapUnitMaxScale" value="0"/>
<property key="labeling/repeatDistanceMapUnitMinScale" value="0"/>
<property key="labeling/repeatDistanceUnit" value="1"/>
<property key="labeling/reverseDirectionSymbol" value="false"/>
<property key="labeling/rightDirectionSymbol" value=">"/>
<property key="labeling/scaleMax" value="10000000"/>
<property key="labeling/scaleMin" value="1"/>
<property key="labeling/scaleVisibility" value="false"/>
<property key="labeling/shadowBlendMode" value="6"/>
<property key="labeling/shadowColorB" value="0"/>
<property key="labeling/shadowColorG" value="0"/>
<property key="labeling/shadowColorR" value="0"/>
<property key="labeling/shadowDraw" value="false"/>
<property key="labeling/shadowOffsetAngle" value="135"/>
<property key="labeling/shadowOffsetDist" value="1"/>
<property key="labeling/shadowOffsetGlobal" value="true"/>
<property key="labeling/shadowOffsetMapUnitMaxScale" value="0"/>
<property key="labeling/shadowOffsetMapUnitMinScale" value="0"/>
<property key="labeling/shadowOffsetUnits" value="1"/>
<property key="labeling/shadowRadius" value="1.5"/>
<property key="labeling/shadowRadiusAlphaOnly" value="false"/>
<property key="labeling/shadowRadiusMapUnitMaxScale" value="0"/>
<property key="labeling/shadowRadiusMapUnitMinScale" value="0"/>
<property key="labeling/shadowRadiusUnits" value="1"/>
<property key="labeling/shadowScale" value="100"/>
<property key="labeling/shadowTransparency" value="30"/>
<property key="labeling/shadowUnder" value="0"/>
<property key="labeling/shapeBlendMode" value="0"/>
<property key="labeling/shapeBorderColorA" value="255"/>
<property key="labeling/shapeBorderColorB" value="128"/>
<property key="labeling/shapeBorderColorG" value="128"/>
<property key="labeling/shapeBorderColorR" value="128"/>
<property key="labeling/shapeBorderWidth" value="0"/>
<property key="labeling/shapeBorderWidthMapUnitMaxScale" value="0"/>
<property key="labeling/shapeBorderWidthMapUnitMinScale" value="0"/>
<property key="labeling/shapeBorderWidthUnits" value="1"/>
<property key="labeling/shapeDraw" value="false"/>
<property key="labeling/shapeFillColorA" value="255"/>
<property key="labeling/shapeFillColorB" value="255"/>
<property key="labeling/shapeFillColorG" value="255"/>
<property key="labeling/shapeFillColorR" value="255"/>
<property key="labeling/shapeJoinStyle" value="64"/>
<property key="labeling/shapeOffsetMapUnitMaxScale" value="0"/>
<property key="labeling/shapeOffsetMapUnitMinScale" value="0"/>
<property key="labeling/shapeOffsetUnits" value="1"/>
<property key="labeling/shapeOffsetX" value="0"/>
<property key="labeling/shapeOffsetY" value="0"/>
<property key="labeling/shapeRadiiMapUnitMaxScale" value="0"/>
<property key="labeling/shapeRadiiMapUnitMinScale" value="0"/>
<property key="labeling/shapeRadiiUnits" value="1"/>
<property key="labeling/shapeRadiiX" value="0"/>
<property key="labeling/shapeRadiiY" value="0"/>
<property key="labeling/shapeRotation" value="0"/>
<property key="labeling/shapeRotationType" value="0"/>
<property key="labeling/shapeSVGFile" value=""/>
<property key="labeling/shapeSizeMapUnitMaxScale" value="0"/>
<property key="labeling/shapeSizeMapUnitMinScale" value="0"/>
<property key="labeling/shapeSizeType" value="0"/>
<property key="labeling/shapeSizeUnits" value="1"/>
<property key="labeling/shapeSizeX" value="0"/>
<property key="labeling/shapeSizeY" value="0"/>
<property key="labeling/shapeTransparency" value="0"/>
<property key="labeling/shapeType" value="0"/>
<property key="labeling/textColorA" value="255"/>
<property key="labeling/textColorB" value="0"/>
<property key="labeling/textColorG" value="0"/>
<property key="labeling/textColorR" value="0"/>
<property key="labeling/textTransp" value="0"/>
<property key="labeling/upsidedownLabels" value="0"/>
<property key="labeling/wrapChar" value=""/>
<property key="labeling/xOffset" value="0"/>
<property key="labeling/yOffset" value="0"/>
<property key="labeling/zIndex" value="0"/>
<property key="variableNames" value="_fields_"/>
<property key="variableValues" value=""/>
</customproperties>
<blendMode>0</blendMode>
<featureBlendMode>0</featureBlendMode>
<layerTransparency>0</layerTransparency>
<displayfield>pkuid</displayfield>
<label>0</label>
<labelattributes>
<label fieldname="" text="Label"/>
<family fieldname="" name="DejaVu Sans"/>
<size fieldname="" units="pt" value="12"/>
<bold fieldname="" on="0"/>
<italic fieldname="" on="0"/>
<underline fieldname="" on="0"/>
<strikeout fieldname="" on="0"/>
<color fieldname="" red="0" blue="0" green="0"/>
<x fieldname=""/>
<y fieldname=""/>
<offset x="0" y="0" units="pt" yfieldname="" xfieldname=""/>
<angle fieldname="" value="0" auto="0"/>
<alignment fieldname="" value="center"/>
<buffercolor fieldname="" red="255" blue="255" green="255"/>
<buffersize fieldname="" units="pt" value="1"/>
<bufferenabled fieldname="" on=""/>
<multilineenabled fieldname="" on=""/>
<selectedonly on=""/>
</labelattributes>
<SingleCategoryDiagramRenderer diagramType="Pie">
<DiagramCategory penColor="#000000" labelPlacementMethod="XHeight" penWidth="0" diagramOrientation="Up" minimumSize="0" barWidth="5" penAlpha="255" maxScaleDenominator="1e+08" backgroundColor="#ffffff" transparency="0" width="15" scaleDependency="Area" backgroundAlpha="255" angleOffset="1440" scaleBasedVisibility="0" enabled="0" height="15" sizeType="MM" minScaleDenominator="0">
<fontProperties description="DejaVu Sans,11,-1,5,50,0,0,0,0,0" style=""/>
<attribute field="" color="#000000" label=""/>
</DiagramCategory>
</SingleCategoryDiagramRenderer>
<DiagramLayerSettings yPosColumn="-1" linePlacementFlags="10" placement="0" dist="0" xPosColumn="-1" priority="0" obstacle="0" zIndex="0" showAll="1"/>
<annotationform>.</annotationform>
<aliases>
<alias field="colour" index="2" name="Couleur"/>
</aliases>
<excludeAttributesWMS/>
<excludeAttributesWFS/>
<attributeactions/>
<editform>.</editform>
<editforminit/>
<editforminitcodesource>0</editforminitcodesource>
<editforminitfilepath>.</editforminitfilepath>
<editforminitcode><![CDATA[# -*- coding: utf-8 -*-
"""
QGIS forms can have a Python function that is called when the form is
opened.
Use this function to add extra logic to your forms.
Enter the name of the function in the "Python Init function"
field.
An example follows:
"""
from PyQt4.QtGui import QWidget
def my_form_open(dialog, layer, feature):
geom = feature.geometry()
control = dialog.findChild(QWidget, "MyLineEdit")
]]></editforminitcode>
<featformsuppress>0</featformsuppress>
<editorlayout>generatedlayout</editorlayout>
<attributeEditorForm>
<attributeEditorContainer name="t">
<attributeEditorContainer name="c1">
<attributeEditorField index="1" name="pkuid"/>
</attributeEditorContainer>
<attributeEditorContainer name="c2">
<attributeEditorField index="2" name="colour"/>
</attributeEditorContainer>
</attributeEditorContainer>
</attributeEditorForm>
<widgets/>
<conditionalstyles>
<rowstyles/>
<fieldstyles/>
</conditionalstyles>
<edittypes>
<edittype widgetv2type="TextEdit" name="pk">
<widgetv2config IsMultiline="0" fieldEditable="1" UseHtml="0" labelOnTop="1"/>
</edittype>
<edittype widgetv2type="TextEdit" name="pkuid">
<widgetv2config IsMultiline="0" fieldEditable="1" UseHtml="0" labelOnTop="0"/>
</edittype>
<edittype widgetv2type="TextEdit" name="colour">
<widgetv2config IsMultiline="0" fieldEditable="1" UseHtml="0" labelOnTop="1"/>
</edittype>
</edittypes>
</maplayer>
<maplayer minimumScale="-4.65661e-10" maximumScale="1e+08" simplifyDrawingHints="1" minLabelScale="1" maxLabelScale="1e+08" simplifyDrawingTol="1" geometry="Polygon" simplifyMaxScale="1" type="vector" hasScaleBasedVisibilityFlag="0" simplifyLocal="1" scaleBasedLabelVisibilityFlag="0">
<id>Hello_SubsetString_copy20160222085231770</id>
<datasource>dbname='./helloworld.db' table="hello" (geom) sql="pkuid" in ( 7, 8 )</datasource>
@ -2331,15 +2658,15 @@ def my_form_open(dialog, layer, feature):
<WMSKeywordList type="QStringList">
<value></value>
</WMSKeywordList>
<Variables>
<variableNames type="QStringList"/>
<variableValues type="QStringList"/>
</Variables>
<Paths>
<Absolute type="bool">false</Absolute>
</Paths>
<WMSContactPosition type="QString"></WMSContactPosition>
<WMSMaxHeight type="int">5000</WMSMaxHeight>
<Variables>
<variableNames type="QStringList"/>
<variableValues type="QStringList"/>
</Variables>
<PositionPrecision>
<DecimalPlaces type="int">2</DecimalPlaces>
<Automatic type="bool">true</Automatic>