From 25f47bbbb66c4db9cb6a0a6325d6fef1da9001bf Mon Sep 17 00:00:00 2001 From: Justin Bronn Date: Wed, 27 Jan 2010 03:32:30 +0000 Subject: [PATCH] Applied DRY and centralized geometry input regular expressions; `OGRGeometry` may now consume and output EWKT. git-svn-id: http://code.djangoproject.com/svn/django/trunk@12302 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/contrib/gis/gdal/geometries.py | 26 +++++++++++++++------- django/contrib/gis/gdal/tests/test_geom.py | 11 +++++++++ django/contrib/gis/geometry/regex.py | 12 ++++++++++ django/contrib/gis/geos/geometry.py | 9 +++----- 4 files changed, 44 insertions(+), 14 deletions(-) create mode 100644 django/contrib/gis/geometry/regex.py diff --git a/django/contrib/gis/gdal/geometries.py b/django/contrib/gis/gdal/geometries.py index b301cc1c27..df5ea70547 100644 --- a/django/contrib/gis/gdal/geometries.py +++ b/django/contrib/gis/gdal/geometries.py @@ -39,7 +39,7 @@ True """ # Python library requisites. -import re, sys +import sys from binascii import a2b_hex from ctypes import byref, string_at, c_char_p, c_double, c_ubyte, c_void_p @@ -54,16 +54,14 @@ from django.contrib.gis.gdal.srs import SpatialReference, CoordTransform from django.contrib.gis.gdal.prototypes import geom as capi, srs as srs_api GEOJSON = capi.GEOJSON +# For recognizing geometry input. +from django.contrib.gis.geometry.regex import hex_regex, wkt_regex, json_regex + # For more information, see the OGR C API source code: # http://www.gdal.org/ogr/ogr__api_8h.html # # The OGR_G_* routines are relevant here. -# Regular expressions for recognizing HEXEWKB and WKT. -hex_regex = re.compile(r'^[0-9A-F]+$', re.I) -wkt_regex = re.compile(r'^(?PPOINT|LINESTRING|LINEARRING|POLYGON|MULTIPOINT|MULTILINESTRING|MULTIPOLYGON|GEOMETRYCOLLECTION)[ACEGIMLONPSRUTY\d,\.\-\(\) ]+$', re.I) -json_regex = re.compile(r'^(\s+)?\{[\s\w,\[\]\{\}\-\."\':]+\}(\s+)?$') - #### OGRGeometry Class #### class OGRGeometry(GDALBase): "Generally encapsulates an OGR geometry." @@ -88,13 +86,16 @@ class OGRGeometry(GDALBase): wkt_m = wkt_regex.match(geom_input) json_m = json_regex.match(geom_input) if wkt_m: + if wkt_m.group('srid'): + # If there's EWKT, set the SRS w/value of the SRID. + srs = int(wkt_m.group('srid')) if wkt_m.group('type').upper() == 'LINEARRING': # OGR_G_CreateFromWkt doesn't work with LINEARRING WKT. # See http://trac.osgeo.org/gdal/ticket/1992. g = capi.create_geom(OGRGeomType(wkt_m.group('type')).num) - capi.import_wkt(g, byref(c_char_p(geom_input))) + capi.import_wkt(g, byref(c_char_p(wkt_m.group('wkt')))) else: - g = capi.from_wkt(byref(c_char_p(geom_input)), None, byref(c_void_p())) + g = capi.from_wkt(byref(c_char_p(wkt_m.group('wkt'))), None, byref(c_void_p())) elif json_m: if GEOJSON: g = capi.from_json(geom_input) @@ -341,6 +342,15 @@ class OGRGeometry(GDALBase): "Returns the WKT representation of the Geometry." return capi.to_wkt(self.ptr, byref(c_char_p())) + @property + def ewkt(self): + "Returns the EWKT representation of the Geometry." + srs = self.srs + if srs and srs.srid: + return 'SRID=%s;%s' % (srs.srid, self.wkt) + else: + return self.wkt + #### Geometry Methods #### def clone(self): "Clones this OGR Geometry." diff --git a/django/contrib/gis/gdal/tests/test_geom.py b/django/contrib/gis/gdal/tests/test_geom.py index 02305f97b4..93f08504a1 100644 --- a/django/contrib/gis/gdal/tests/test_geom.py +++ b/django/contrib/gis/gdal/tests/test_geom.py @@ -59,6 +59,17 @@ class OGRGeomTest(unittest.TestCase): geom = OGRGeometry(g.wkt) self.assertEqual(g.wkt, geom.wkt) + def test01a_ewkt(self): + "Testing EWKT input/output." + for ewkt_val in ('POINT (1 2 3)', 'LINEARRING (0 0,1 1,2 1,0 0)'): + # First with ewkt output when no SRID in EWKT + self.assertEqual(ewkt_val, OGRGeometry(ewkt_val).ewkt) + # No test consumption with an SRID specified. + ewkt_val = 'SRID=4326;%s' % ewkt_val + geom = OGRGeometry(ewkt_val) + self.assertEqual(ewkt_val, geom.ewkt) + self.assertEqual(4326, geom.srs.srid) + def test01b_gml(self): "Testing GML output." for g in wkt_out: diff --git a/django/contrib/gis/geometry/regex.py b/django/contrib/gis/geometry/regex.py new file mode 100644 index 0000000000..85238581bf --- /dev/null +++ b/django/contrib/gis/geometry/regex.py @@ -0,0 +1,12 @@ +import re + +# Regular expression for recognizing HEXEWKB and WKT. A prophylactic measure +# to prevent potentially malicious input from reaching the underlying C +# library. Not a substitute for good web security programming practices. +hex_regex = re.compile(r'^[0-9A-F]+$', re.I) +wkt_regex = re.compile(r'^(SRID=(?P\d+);)?' + r'(?P' + r'(?PPOINT|LINESTRING|LINEARRING|POLYGON|MULTIPOINT|MULTILINESTRING|MULTIPOLYGON|GEOMETRYCOLLECTION)' + r'[ACEGIMLONPSRUTYZ\d,\.\-\(\) ]+)$', + re.I) +json_regex = re.compile(r'^(\s+)?\{[\s\w,\[\]\{\}\-\."\':]+\}(\s+)?$') diff --git a/django/contrib/gis/geos/geometry.py b/django/contrib/gis/geos/geometry.py index 84b0454921..c508431c2a 100644 --- a/django/contrib/gis/geos/geometry.py +++ b/django/contrib/gis/geos/geometry.py @@ -25,11 +25,8 @@ from django.contrib.gis.geos import prototypes as capi # of their corresponding GEOS I/O class. from django.contrib.gis.geos.prototypes.io import wkt_r, wkt_w, wkb_r, wkb_w, ewkb_w, ewkb_w3d -# Regular expression for recognizing HEXEWKB and WKT. A prophylactic measure -# to prevent potentially malicious input from reaching the underlying C -# library. Not a substitute for good web security programming practices. -hex_regex = re.compile(r'^[0-9A-F]+$', re.I) -wkt_regex = re.compile(r'^(SRID=(?P\d+);)?(?P(POINT|LINESTRING|LINEARRING|POLYGON|MULTIPOINT|MULTILINESTRING|MULTIPOLYGON|GEOMETRYCOLLECTION)[ACEGIMLONPSRUTY\d,\.\-\(\) ]+)$', re.I) +# For recognizing geometry input. +from django.contrib.gis.geometry.regex import hex_regex, wkt_regex, json_regex class GEOSGeometry(GEOSBase, ListMixin): "A class that, generally, encapsulates a GEOS geometry." @@ -69,7 +66,7 @@ class GEOSGeometry(GEOSBase, ListMixin): elif hex_regex.match(geo_input): # Handling HEXEWKB input. g = wkb_r().read(geo_input) - elif gdal.GEOJSON and gdal.geometries.json_regex.match(geo_input): + elif gdal.GEOJSON and json_regex.match(geo_input): # Handling GeoJSON input. g = wkb_r().read(gdal.OGRGeometry(geo_input).wkb) else: