diff --git a/bindings/python/mapnik/ogcserver/WMS.py b/bindings/python/mapnik/ogcserver/WMS.py
deleted file mode 100644
index fefb66d46..000000000
--- a/bindings/python/mapnik/ogcserver/WMS.py
+++ /dev/null
@@ -1,125 +0,0 @@
-#
-# This file is part of Mapnik (c++ mapping toolkit)
-#
-# Copyright (C) 2006 Jean-Francois Doyon
-#
-# Mapnik is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-#
-# $Id$
-
-"""Interface for registering map styles and layers for availability in WMS Requests."""
-
-from common import Version, copy_style, copy_layer
-from exceptions import OGCException, ServerConfigurationError
-from wms111 import ServiceHandler as ServiceHandler111
-from wms130 import ServiceHandler as ServiceHandler130
-from mapnik import Style, Map, load_map
-import re
-import sys
-
-def ServiceHandlerFactory(conf, mapfactory, onlineresource, version):
-
- if not version:
- version = Version('1.3.0')
- else:
- version = Version(version)
- if version >= '1.3.0':
- return ServiceHandler130(conf, mapfactory, onlineresource)
- else:
- return ServiceHandler111(conf, mapfactory, onlineresource)
-
-class BaseWMSFactory:
- def __init__(self):
- self.layers = {}
- self.ordered_layers = []
- self.styles = {}
- self.aggregatestyles = {}
-
- def loadXML(self, xmlfile, strict=False):
- tmp_map = Map(0,0)
- load_map (tmp_map, xmlfile, strict)
- for lyr in tmp_map.layers:
- style_count = len(lyr.styles)
- if style_count == 0:
- raise ServerConfigurationError("Cannot register Layer '%s' without a style" % lyr.name)
- elif style_count == 1:
- style_obj = tmp_map.find_style(lyr.styles[0])
- style_obj = copy_style(style_obj)
- style_name = lyr.styles[0]
- if style_name not in self.aggregatestyles.keys() and style_name not in self.styles.keys():
- self.register_style(style_name, style_obj)
- self.register_layer(copy_layer(lyr), style_name, extrastyles=(style_name,))
- elif style_count > 1:
- for style_name in lyr.styles:
- style_obj = tmp_map.find_style(style_name)
- style_obj = copy_style(style_obj)
- if style_name not in self.aggregatestyles.keys() and style_name not in self.styles.keys():
- self.register_style(style_name, style_obj)
- aggregates = tuple([sty for sty in lyr.styles])
- aggregates_name = '%s_aggregates' % lyr.name
- self.register_aggregate_style(aggregates_name,aggregates)
- self.register_layer(copy_layer(lyr), aggregates_name, extrastyles=aggregates)
-
- def register_layer(self, layer, defaultstyle, extrastyles=()):
- layername = layer.name
- if not layername:
- raise ServerConfigurationError('Attempted to register an unnamed layer.')
- if not re.match('^\+init=epsg:\d+$', layer.srs) and not re.match('^\+proj=.*$', layer.srs):
- raise ServerConfigurationError('Attempted to register a layer without an epsg projection defined.')
- if defaultstyle not in self.styles.keys() + self.aggregatestyles.keys():
- raise ServerConfigurationError('Attempted to register a layer with an non-existent default style.')
- layer.wmsdefaultstyle = defaultstyle
- if isinstance(extrastyles, tuple):
- for stylename in extrastyles:
- if type(stylename) == type(''):
- if stylename not in self.styles.keys() + self.aggregatestyles.keys():
- raise ServerConfigurationError('Attempted to register a layer with an non-existent extra style.')
- else:
- ServerConfigurationError('Attempted to register a layer with an invalid extra style name.')
- layer.wmsextrastyles = extrastyles
- else:
- raise ServerConfigurationError('Layer "%s" was passed an invalid list of extra styles. List must be a tuple of strings.' % layername)
- self.ordered_layers.append(layer)
- self.layers[layername] = layer
-
- def register_style(self, name, style):
- if not name:
- raise ServerConfigurationError('Attempted to register a style without providing a name.')
- if name in self.aggregatestyles.keys() or name in self.styles.keys():
- raise ServerConfigurationError("Attempted to register a style with a name already in use: '%s'" % name)
- if not isinstance(style, Style):
- raise ServerConfigurationError('Bad style object passed to register_style() for style "%s".' % name)
- self.styles[name] = style
-
- def register_aggregate_style(self, name, stylenames):
- if not name:
- raise ServerConfigurationError('Attempted to register an aggregate style without providing a name.')
- if name in self.aggregatestyles.keys() or name in self.styles.keys():
- raise ServerConfigurationError('Attempted to register an aggregate style with a name already in use.')
- self.aggregatestyles[name] = []
- for stylename in stylenames:
- if stylename not in self.styles.keys():
- raise ServerConfigurationError('Attempted to register an aggregate style containing a style that does not exist.')
- self.aggregatestyles[name].append(stylename)
-
- def finalize(self):
- if len(self.layers) == 0:
- raise ServerConfigurationError('No layers defined!')
- if len(self.styles) == 0:
- raise ServerConfigurationError('No styles defined!')
- for layer in self.layers.values():
- for style in list(layer.styles) + list(layer.wmsextrastyles):
- if style not in self.styles.keys() + self.aggregatestyles.keys():
- raise ServerConfigurationError('Layer "%s" refers to undefined style "%s".' % (layer.name, style))
diff --git a/bindings/python/mapnik/ogcserver/__init__.py b/bindings/python/mapnik/ogcserver/__init__.py
deleted file mode 100644
index 45456fd00..000000000
--- a/bindings/python/mapnik/ogcserver/__init__.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# This file is part of Mapnik (c++ mapping toolkit)
-#
-# Copyright (C) 2006 Jean-Francois Doyon
-#
-# Mapnik is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-#
-# $Id$
-
-"""Mapnik OGC WMS Server."""
-
-import os
-import warnings
-
-warnings.warn("ogcserver module development has moved to https://github.com/mapnik/OGCServer.\n This code will function fine with this version, but will be removed in Mapnik 2.1.0. Disable this warning by editing this file: %s" % os.path.realpath(__file__), DeprecationWarning, 2)
-
diff --git a/bindings/python/mapnik/ogcserver/cgiserver.py b/bindings/python/mapnik/ogcserver/cgiserver.py
deleted file mode 100644
index 3acbebbfd..000000000
--- a/bindings/python/mapnik/ogcserver/cgiserver.py
+++ /dev/null
@@ -1,116 +0,0 @@
-#
-# This file is part of Mapnik (c++ mapping toolkit)
-#
-# Copyright (C) 2006 Jean-Francois Doyon
-#
-# Mapnik is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-#
-# $Id$
-
-"""CGI/FastCGI handler for Mapnik OGC WMS Server.
-
-Requires 'jon' module.
-
-"""
-
-from os import environ
-from tempfile import gettempdir
-environ['PYTHON_EGG_CACHE'] = gettempdir()
-
-import sys
-from jon import cgi
-from exceptions import OGCException, ServerConfigurationError
-from wms111 import ExceptionHandler as ExceptionHandler111
-from wms130 import ExceptionHandler as ExceptionHandler130
-from configparser import SafeConfigParser
-from common import Version
-
-class Handler(cgi.DebugHandler):
-
- def __init__(self):
- conf = SafeConfigParser()
- conf.readfp(open(self.configpath))
- self.conf = conf
- if not conf.has_option_with_value('server', 'module'):
- raise ServerConfigurationError('The factory module is not defined in the configuration file.')
- try:
- mapfactorymodule = __import__(conf.get('server', 'module'))
- except ImportError:
- raise ServerConfigurationError('The factory module could not be loaded.')
- if hasattr(mapfactorymodule, 'WMSFactory'):
- self.mapfactory = getattr(mapfactorymodule, 'WMSFactory')()
- else:
- raise ServerConfigurationError('The factory module does not have a WMSFactory class.')
- if conf.has_option('server', 'debug'):
- self.debug = int(conf.get('server', 'debug'))
- else:
- self.debug = 0
-
- def process(self, req):
- reqparams = lowerparams(req.params)
- onlineresource = 'http://%s:%s%s?' % (req.environ['SERVER_NAME'], req.environ['SERVER_PORT'], req.environ['SCRIPT_NAME'])
- if not reqparams.has_key('request'):
- raise OGCException('Missing request parameter.')
- request = reqparams['request']
- del reqparams['request']
- if request == 'GetCapabilities' and not reqparams.has_key('service'):
- raise OGCException('Missing service parameter.')
- if request in ['GetMap', 'GetFeatureInfo']:
- service = 'WMS'
- else:
- service = reqparams['service']
- if reqparams.has_key('service'):
- del reqparams['service']
- try:
- mapnikmodule = __import__('mapnik.ogcserver.' + service)
- except:
- raise OGCException('Unsupported service "%s".' % service)
- ServiceHandlerFactory = getattr(mapnikmodule.ogcserver, service).ServiceHandlerFactory
- servicehandler = ServiceHandlerFactory(self.conf, self.mapfactory, onlineresource, reqparams.get('version', None))
- if reqparams.has_key('version'):
- del reqparams['version']
- if request not in servicehandler.SERVICE_PARAMS.keys():
- raise OGCException('Operation "%s" not supported.' % request, 'OperationNotSupported')
- ogcparams = servicehandler.processParameters(request, reqparams)
- try:
- requesthandler = getattr(servicehandler, request)
- except:
- raise OGCException('Operation "%s" not supported.' % request, 'OperationNotSupported')
- response = requesthandler(ogcparams)
- req.set_header('Content-Type', response.content_type)
- req.set_header('Content-Length', str(len(response.content)))
- req.write(response.content)
-
- def traceback(self, req):
- reqparams = lowerparams(req.params)
- version = reqparams.get('version', None)
- if not version:
- version = Version('1.3.0')
- else:
- version = Version(version)
- if version >= '1.3.0':
- eh = ExceptionHandler130(self.debug)
- else:
- eh = ExceptionHandler111(self.debug)
- response = eh.getresponse(reqparams)
- req.set_header('Content-Type', response.content_type)
- req.set_header('Content-Length', str(len(response.content)))
- req.write(response.content)
-
-def lowerparams(params):
- reqparams = {}
- for key, value in params.items():
- reqparams[key.lower()] = value
- return reqparams
diff --git a/bindings/python/mapnik/ogcserver/common.py b/bindings/python/mapnik/ogcserver/common.py
deleted file mode 100644
index c55a042f2..000000000
--- a/bindings/python/mapnik/ogcserver/common.py
+++ /dev/null
@@ -1,539 +0,0 @@
-#
-# This file is part of Mapnik (c++ mapping toolkit)
-#
-# Copyright (C) 2006 Jean-Francois Doyon
-#
-# Mapnik is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-#
-# $Id$
-
-"""Core OGCServer classes and functions."""
-
-from exceptions import OGCException, ServerConfigurationError
-from mapnik import Map, Color, Box2d, render, Image, Layer, Style, Projection as MapnikProjection, Coord
-from PIL.Image import new
-from PIL.ImageDraw import Draw
-from StringIO import StringIO
-from copy import deepcopy
-from traceback import format_exception, format_exception_only
-from sys import exc_info
-import re
-import sys
-
-try:
- from lxml import etree as ElementTree
-except ImportError:
- import xml.etree.ElementTree as ElementTree
-except ImportError:
- import elementtree.ElementTree as ElementTree
-
-# from elementtree import ElementTree
-# ElementTree._namespace_map.update({'http://www.opengis.net/wms': 'wms',
-# 'http://www.opengis.net/ogc': 'ogc',
-# 'http://www.w3.org/1999/xlink': 'xlink',
-# 'http://www.w3.org/2001/XMLSchema-instance': 'xsi'
-# })
-
-PIL_TYPE_MAPPING = {'image/jpeg': 'jpeg', 'image/png': 'png'}
-
-class ParameterDefinition:
-
- def __init__(self, mandatory, cast, default=None, allowedvalues=None, fallback=False):
- """ An OGC request parameter definition. Used to describe a
- parameter's characteristics.
-
- @param mandatory: Is this parameter required by the request?
- @type mandatory: Boolean.
-
- @param default: Default value to use if one is not provided
- and the parameter is optional.
- @type default: None or any valid value.
-
- @param allowedvalues: A list of allowed values for the parameter.
- If a value is provided that is not in this
- list, an error is raised.
- @type allowedvalues: A python tuple of values.
-
- @param fallback: Whether the value of the parameter should fall
- back to the default should an illegal value be
- provided.
- @type fallback: Boolean.
-
- @return: A L{ParameterDefinition} instance.
- """
- if mandatory not in [True, False]:
- raise ServerConfigurationError("Bad value for 'mandatory' parameter, must be True or False.")
- self.mandatory = mandatory
- if not callable(cast):
- raise ServerConfigurationError('Cast parameter definition must be callable.')
- self.cast = cast
- self.default = default
- if allowedvalues and type(allowedvalues) != type(()):
- raise ServerConfigurationError("Bad value for 'allowedvalues' parameter, must be a tuple.")
- self.allowedvalues = allowedvalues
- if fallback not in [True, False]:
- raise ServerConfigurationError("Bad value for 'fallback' parameter, must be True or False.")
- self.fallback = fallback
-
-class BaseServiceHandler:
-
- CONF_CONTACT_PERSON_PRIMARY = [
- ['contactperson', 'ContactPerson', str],
- ['contactorganization', 'ContactOrganization', str]
- ]
-
- CONF_CONTACT_ADDRESS = [
- ['addresstype', 'AddressType', str],
- ['address', 'Address', str],
- ['city', 'City', str],
- ['stateorprovince', 'StateOrProvince', str],
- ['postcode', 'PostCode', str],
- ['country', 'Country', str]
- ]
-
- CONF_CONTACT = [
- ['contactposition', 'ContactPosition', str],
- ['contactvoicetelephone', 'ContactVoiceTelephone', str],
- ['contactelectronicmailaddress', 'ContactElectronicMailAddress', str]
- ]
-
- def processParameters(self, requestname, params):
- finalparams = {}
- for paramname, paramdef in self.SERVICE_PARAMS[requestname].items():
- if paramname not in params.keys() and paramdef.mandatory:
- raise OGCException('Mandatory parameter "%s" missing from request.' % paramname)
- elif paramname in params.keys():
- try:
- params[paramname] = paramdef.cast(params[paramname])
- except OGCException:
- raise
- except:
- raise OGCException('Invalid value "%s" for parameter "%s".' % (params[paramname], paramname))
- if paramdef.allowedvalues and params[paramname] not in paramdef.allowedvalues:
- if not paramdef.fallback:
- raise OGCException('Parameter "%s" has an illegal value.' % paramname)
- else:
- finalparams[paramname] = paramdef.default
- else:
- finalparams[paramname] = params[paramname]
- elif not paramdef.mandatory and paramdef.default:
- finalparams[paramname] = paramdef.default
- return finalparams
-
- def processServiceCapabilities(self, capetree):
- if len(self.conf.items('service')) > 0:
- servicee = capetree.find('{http://www.opengis.net/wms}Service')
- for item in self.CONF_SERVICE:
- if self.conf.has_option_with_value('service', item[0]):
- value = self.conf.get('service', item[0]).strip()
- try:
- item[2](value)
- except:
- raise ServerConfigurationError('Configuration parameter [%s]->%s has an invalid value: %s.' % ('service', item[0], value))
- if item[0] == 'onlineresource':
- element = ElementTree.Element('%s' % item[1])
- servicee.append(element)
- element.set('{http://www.w3.org/1999/xlink}href', value)
- element.set('{http://www.w3.org/1999/xlink}type', 'simple')
- elif item[0] == 'keywordlist':
- element = ElementTree.Element('%s' % item[1])
- servicee.append(element)
- keywords = value.split(',')
- keywords = map(str.strip, keywords)
- for keyword in keywords:
- kelement = ElementTree.Element('Keyword')
- kelement.text = keyword
- element.append(kelement)
- else:
- element = ElementTree.Element('%s' % item[1])
- element.text = value
- servicee.append(element)
- if len(self.conf.items_with_value('contact')) > 0:
- element = ElementTree.Element('ContactInformation')
- servicee.append(element)
- for item in self.CONF_CONTACT:
- if self.conf.has_option_with_value('contact', item[0]):
- value = self.conf.get('contact', item[0]).strip()
- try:
- item[2](value)
- except:
- raise ServerConfigurationError('Configuration parameter [%s]->%s has an invalid value: %s.' % ('service', item[0], value))
- celement = ElementTree.Element('%s' % item[1])
- celement.text = value
- element.append(celement)
- for item in self.CONF_CONTACT_PERSON_PRIMARY + self.CONF_CONTACT_ADDRESS:
- if item in self.CONF_CONTACT_PERSON_PRIMARY:
- tagname = 'ContactPersonPrimary'
- else:
- tagname = 'ContactAddress'
- if self.conf.has_option_with_value('contact', item[0]):
- if element.find(tagname) == None:
- subelement = ElementTree.Element(tagname)
- element.append(subelement)
- value = self.conf.get('contact', item[0]).strip()
- try:
- item[2](value)
- except:
- raise ServerConfigurationError('Configuration parameter [%s]->%s has an invalid value: %s.' % ('service', item[0], value))
- celement = ElementTree.Element('%s' % item[1])
- celement.text = value
- subelement.append(celement)
-
-class Response:
-
- def __init__(self, content_type, content):
- self.content_type = content_type
- self.content = content
-
-class Version:
-
- def __init__(self, version):
- version = version.split('.')
- if len(version) != 3:
- raise OGCException('Badly formatted version number.')
- try:
- version = map(int, version)
- except:
- raise OGCException('Badly formatted version number.')
- self.version = version
-
- def __repr__(self):
- return '%s.%s.%s' % (self.version[0], self.version[1], self.version[2])
-
- def __cmp__(self, other):
- if isinstance(other, str):
- other = Version(other)
- if self.version[0] < other.version[0]:
- return -1
- elif self.version[0] > other.version[0]:
- return 1
- else:
- if self.version[1] < other.version[1]:
- return -1
- elif self.version[1] > other.version[1]:
- return 1
- else:
- if self.version[2] < other.version[2]:
- return -1
- elif self.version[2] > other.version[2]:
- return 1
- else:
- return 0
-
-class ListFactory:
-
- def __init__(self, cast):
- self.cast = cast
-
- def __call__(self, string):
- seq = string.split(',')
- return map(self.cast, seq)
-
-def ColorFactory(colorstring):
- if re.match('^0x[a-fA-F0-9]{6}$', colorstring):
- return Color(eval('0x' + colorstring[2:4]), eval('0x' + colorstring[4:6]), eval('0x' + colorstring[6:8]))
- else:
- raise OGCException('Invalid color value. Must be of format "0xFFFFFF".')
-
-class CRS:
-
- def __init__(self, namespace, code):
- self.namespace = namespace.lower()
- self.code = int(code)
- self.proj = None
-
- def __repr__(self):
- return '%s:%s' % (self.namespace, self.code)
-
- def __eq__(self, other):
- if str(other) == str(self):
- return True
- return False
-
- def inverse(self, x, y):
- if not self.proj:
- self.proj = Projection('+init=%s:%s' % (self.namespace, self.code))
- return self.proj.inverse(Coord(x, y))
-
- def forward(self, x, y):
- if not self.proj:
- self.proj = Projection('+init=%s:%s' % (self.namespace, self.code))
- return self.proj.forward(Coord(x, y))
-
-class CRSFactory:
-
- def __init__(self, allowednamespaces):
- self.allowednamespaces = allowednamespaces
-
- def __call__(self, crsstring):
- if not re.match('^[A-Z]{3,5}:\d+$', crsstring):
- raise OGCException('Invalid format for the CRS parameter: %s' % crsstring, 'InvalidCRS')
- crsparts = crsstring.split(':')
- if crsparts[0] in self.allowednamespaces:
- return CRS(crsparts[0], crsparts[1])
- else:
- raise OGCException('Invalid CRS Namespace: %s' % crsparts[0], 'InvalidCRS')
-
-def copy_layer(obj):
- lyr = Layer(obj.name)
- lyr.abstract = obj.abstract
- lyr.active = obj.active
- lyr.clear_label_cache = obj.clear_label_cache
- lyr.datasource = obj.datasource
- #lyr.maxzoom = obj.maxzoom
- #lyr.minzoom = obj.minzoom
- lyr.queryable = obj.queryable
- lyr.srs = obj.srs
- lyr.title = obj.title
- if hasattr(obj,'wmsdefaultstyle'):
- lyr.wmsdefaultstyle = obj.wmsdefaultstyle
- if hasattr(obj,'wmsextrastyles'):
- lyr.wmsextrastyles = obj.wmsextrastyles
- return lyr
-
-def copy_style(obj):
- sty = Style()
- for rule in obj.rules:
- sty.rules.append(rule)
- return sty
-
-class WMSBaseServiceHandler(BaseServiceHandler):
-
- def GetMap(self, params):
- m = self._buildMap(params)
- im = Image(params['width'], params['height'])
- render(m, im)
- return Response(params['format'], im.tostring(PIL_TYPE_MAPPING[params['format']]))
-
- def GetFeatureInfo(self, params, querymethodname='query_point'):
- m = self._buildMap(params)
- if params['info_format'] == 'text/plain':
- writer = TextFeatureInfo()
- elif params['info_format'] == 'text/xml':
- writer = XMLFeatureInfo()
- if params['query_layers'] and params['query_layers'][0] == '__all__':
- for layerindex, layer in enumerate(m.layers):
- featureset = getattr(m, querymethodname)(layerindex, params['i'], params['j'])
- features = featureset.features
- if features:
- writer.addlayer(layer.name)
- for feat in features:
- writer.addfeature()
- for prop in feat.properties:
- writer.addattribute(prop[0], prop[1])
- else:
- for layerindex, layername in enumerate(params['query_layers']):
- if layername in params['layers']:
- if m.layers[layerindex].queryable:
- featureset = getattr(m, querymethodname)(layerindex, params['i'], params['j'])
- features = featureset.features
- if features:
- writer.addlayer(m.layers[layerindex].name)
- for feat in features:
- writer.addfeature()
- for prop in feat.properties:
- writer.addattribute(prop[0], prop[1])
- else:
- raise OGCException('Requested query layer "%s" is not marked queryable.' % layername, 'LayerNotQueryable')
- else:
- raise OGCException('Requested query layer "%s" not in the LAYERS parameter.' % layername)
- return Response(params['info_format'], str(writer))
-
- def _buildMap(self, params):
- if str(params['crs']) not in self.allowedepsgcodes:
- raise OGCException('Unsupported CRS "%s" requested.' % str(params['crs']).upper(), 'InvalidCRS')
- if params['bbox'][0] >= params['bbox'][2]:
- raise OGCException("BBOX values don't make sense. minx is greater than maxx.")
- if params['bbox'][1] >= params['bbox'][3]:
- raise OGCException("BBOX values don't make sense. miny is greater than maxy.")
- if params.has_key('styles') and len(params['styles']) != len(params['layers']):
- raise OGCException('STYLES length does not match LAYERS length.')
- m = Map(params['width'], params['height'], '+init=%s' % params['crs'])
- if params.has_key('transparent') and params['transparent'] == 'FALSE':
- if params['bgcolor']:
- m.background = params['bgcolor']
- else:
- m.background = Color(0, 0, 0, 0)
- maplayers = self.mapfactory.layers
- orderedmaplayers = self.mapfactory.ordered_layers
- mapstyles = self.mapfactory.styles
- mapaggregatestyles = self.mapfactory.aggregatestyles
- # a non WMS spec way of requesting all layers
- if params['layers'] and params['layers'][0] == '__all__':
- for layername in orderedmaplayers:
- layer = copy_layer(layername)
- reqstyle = layer.wmsdefaultstyle
- if reqstyle in mapaggregatestyles.keys():
- for stylename in mapaggregatestyles[reqstyle]:
- layer.styles.append(stylename)
- else:
- layer.styles.append(reqstyle)
- for stylename in layer.styles:
- if stylename in mapstyles.keys():
- m.append_style(stylename, mapstyles[stylename])
- m.layers.append(layer)
- else:
- for layerindex, layername in enumerate(params['layers']):
- try:
- layer = copy_layer(maplayers[layername])
- except KeyError:
- raise OGCException('Layer "%s" not defined.' % layername, 'LayerNotDefined')
- try:
- reqstyle = params['styles'][layerindex]
- except IndexError:
- reqstyle = ''
- if reqstyle and reqstyle not in layer.wmsextrastyles:
- raise OGCException('Invalid style "%s" requested for layer "%s".' % (reqstyle, layername), 'StyleNotDefined')
- if not reqstyle:
- reqstyle = layer.wmsdefaultstyle
- if reqstyle in mapaggregatestyles.keys():
- for stylename in mapaggregatestyles[reqstyle]:
- layer.styles.append(stylename)
- else:
- layer.styles.append(reqstyle)
- for stylename in layer.styles:
- if stylename in mapstyles.keys():
- m.append_style(stylename, mapstyles[stylename])
- else:
- raise ServerConfigurationError('Layer "%s" refers to non-existent style "%s".' % (layername, stylename))
- m.layers.append(layer)
- m.zoom_to_box(Box2d(params['bbox'][0], params['bbox'][1], params['bbox'][2], params['bbox'][3]))
- return m
-
-class BaseExceptionHandler:
-
- def __init__(self, debug):
- self.debug = debug
-
- def getresponse(self, params):
- code = ''
- message = '\n'
- if not params:
- message = '''
-
Welcome to the Mapnik OGCServer.
- Ready to accept map requests...
-
- '''
- return self.htmlhandler('', message)
- excinfo = exc_info()
- if self.debug:
- messagelist = format_exception(excinfo[0], excinfo[1], excinfo[2])
- else:
- messagelist = format_exception_only(excinfo[0], excinfo[1])
- message += ''.join(messagelist)
- if isinstance(excinfo[1], OGCException) and len(excinfo[1].args) > 1:
- code = excinfo[1].args[1]
- exceptions = params.get('exceptions', None)
- if self.debug:
- return self.htmlhandler(code, message)
- if not exceptions or not self.handlers.has_key(exceptions):
- exceptions = self.defaulthandler
- return self.handlers[exceptions](self, code, message, params)
-
- def htmlhandler(self,code,message):
- if code:
- resp_text = 'OGCServer Error:
%s
\nTraceback:
%s
\n' % (message, code)
- else:
- resp_text = message
- return Response('text/html', resp_text)
-
- def xmlhandler(self, code, message, params):
- ogcexcetree = deepcopy(self.xmltemplate)
- e = ogcexcetree.find(self.xpath)
- e.text = message
- if code:
- e.set('code', code)
- return Response(self.xmlmimetype, ElementTree.tostring(ogcexcetree))
-
- def inimagehandler(self, code, message, params):
- im = new('RGBA', (int(params['width']), int(params['height'])))
- im.putalpha(new('1', (int(params['width']), int(params['height']))))
- draw = Draw(im)
- for count, line in enumerate(message.strip().split('\n')):
- draw.text((12,15*(count+1)), line, fill='#000000')
- fh = StringIO()
- im.save(fh, PIL_TYPE_MAPPING[params['format']])
- fh.seek(0)
- return Response(params['format'], fh.read())
-
- def blankhandler(self, code, message, params):
- bgcolor = params.get('bgcolor', '#FFFFFF')
- bgcolor = bgcolor.replace('0x', '#')
- transparent = params.get('transparent', 'FALSE')
- if transparent == 'TRUE':
- im = new('RGBA', (int(params['width']), int(params['height'])))
- im.putalpha(new('1', (int(params['width']), int(params['height']))))
- else:
- im = new('RGBA', (int(params['width']), int(params['height'])), bgcolor)
- fh = StringIO()
- im.save(fh, PIL_TYPE_MAPPING[params['format']])
- fh.seek(0)
- return Response(params['format'], fh.read())
-
-class Projection(MapnikProjection):
-
- def epsgstring(self):
- return self.params().split('=')[1].upper()
-
-class TextFeatureInfo:
-
- def __init__(self):
- self.buffer = ''
-
- def addlayer(self, name):
- self.buffer += '\n[%s]\n' % name
-
- def addfeature(self):
- pass#self.buffer += '\n'
-
- def addattribute(self, name, value):
- self.buffer += '%s=%s\n' % (name, str(value))
-
- def __str__(self):
- return self.buffer
-
-class XMLFeatureInfo:
-
- basexml = """
-
-
- """
-
- def __init__(self):
- self.rootelement = ElementTree.fromstring(self.basexml)
-
- def addlayer(self, name):
- layer = ElementTree.Element('layer')
- layer.set('name', name)
- self.rootelement.append(layer)
- self.currentlayer = layer
-
- def addfeature(self):
- feature = ElementTree.Element('feature')
- self.currentlayer.append(feature)
- self.currentfeature = feature
-
- def addattribute(self, name, value):
- attribute = ElementTree.Element('attribute')
- attname = ElementTree.Element('name')
- attname.text = name
- attvalue = ElementTree.Element('value')
- attvalue.text = unicode(value)
- attribute.append(attname)
- attribute.append(attvalue)
- self.currentfeature.append(attribute)
-
- def __str__(self):
- return '\n' + ElementTree.tostring(self.rootelement)
diff --git a/bindings/python/mapnik/ogcserver/configparser.py b/bindings/python/mapnik/ogcserver/configparser.py
deleted file mode 100644
index 99788412d..000000000
--- a/bindings/python/mapnik/ogcserver/configparser.py
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# This file is part of Mapnik (c++ mapping toolkit)
-#
-# Copyright (C) 2006 Jean-Francois Doyon
-#
-# Mapnik is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-#
-# $Id$
-
-""" Change SafeConfigParser behavior to treat options without values as
- non-existent.
-"""
-
-from ConfigParser import SafeConfigParser as OrigSafeConfigParser
-
-class SafeConfigParser(OrigSafeConfigParser):
-
- def items_with_value(self, section):
- finallist = []
- items = self.items(section)
- for item in items:
- if item[1] != '':
- finallist.append(item)
- return finallist
-
- def has_option_with_value(self, section, option):
- if self.has_option(section, option):
- if self.get(section, option) == '':
- return False
- else:
- return False
- return True
\ No newline at end of file
diff --git a/bindings/python/mapnik/ogcserver/exceptions.py b/bindings/python/mapnik/ogcserver/exceptions.py
deleted file mode 100644
index 0ef7dcaf0..000000000
--- a/bindings/python/mapnik/ogcserver/exceptions.py
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# This file is part of Mapnik (c++ mapping toolkit)
-#
-# Copyright (C) 2006 Jean-Francois Doyon
-#
-# Mapnik is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-#
-# $Id$
-
-"""Custom OGCServer Exceptions"""
-
-class OGCException(Exception):
- pass
-
-class ServerConfigurationError(Exception):
- pass
\ No newline at end of file
diff --git a/bindings/python/mapnik/ogcserver/modserver.py b/bindings/python/mapnik/ogcserver/modserver.py
deleted file mode 100644
index 22a260aee..000000000
--- a/bindings/python/mapnik/ogcserver/modserver.py
+++ /dev/null
@@ -1,133 +0,0 @@
-#
-# This file is part of Mapnik (c++ mapping toolkit)
-#
-# Copyright (C) 2006 Jean-Francois Doyon
-#
-# Mapnik is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-#
-# $Id: modserver.py 283 2006-07-22 18:54:53Z jdoyon $
-
-"""Mod_python handler for Mapnik OGC WMS Server."""
-
-import sys
-from mod_python import apache, util
-from exceptions import OGCException, ServerConfigurationError
-from wms111 import ExceptionHandler as ExceptionHandler111
-from wms130 import ExceptionHandler as ExceptionHandler130
-from configparser import SafeConfigParser
-from common import Version
-
-
-class ModHandler(object):
- def __init__(self, configpath):
- conf = SafeConfigParser()
- conf.readfp(open(configpath))
- self.conf = conf
- if not conf.has_option_with_value('server', 'module'):
- raise ServerConfigurationError('The factory module is not defined in the configuration file.')
- try:
- mapfactorymodule = __import__(conf.get('server', 'module'))
- except ImportError:
- raise ServerConfigurationError('The factory module could not be loaded.')
- if hasattr(mapfactorymodule, 'WMSFactory'):
- self.mapfactory = getattr(mapfactorymodule, 'WMSFactory')()
- else:
- raise ServerConfigurationError('The factory module does not have a WMSFactory class.')
- if conf.has_option('server', 'debug'):
- self.debug = int(conf.get('server', 'debug'))
- else:
- self.debug = 0
- if self.conf.has_option_with_value('server', 'maxage'):
- self.max_age = 'max-age=%d' % self.conf.get('server', 'maxage')
- else:
- self.max_age = None
-
- def __call__(self, apacheReq):
- try:
- reqparams = util.FieldStorage(apacheReq,keep_blank_values=1)
- if not reqparams:
- eh = ExceptionHandler130(self.debug)
- response = eh.getresponse(reqparams)
- apacheReq.content_type = response.content_type
- else:
- reqparams = lowerparams(reqparams)
- port = apacheReq.connection.local_addr[1]
- onlineresource = 'http://%s:%s%s?' % (apacheReq.hostname, port, apacheReq.subprocess_env['SCRIPT_NAME'])
- if not reqparams.has_key('request'):
- raise OGCException('Missing Request parameter.')
- request = reqparams['request']
- del reqparams['request']
- if request == 'GetCapabilities' and not reqparams.has_key('service'):
- raise OGCException('Missing service parameter.')
- if request in ['GetMap', 'GetFeatureInfo']:
- service = 'WMS'
- else:
- service = reqparams['service']
- if reqparams.has_key('service'):
- del reqparams['service']
- try:
- mapnikmodule = __import__('mapnik.ogcserver.' + service)
- except:
- raise OGCException('Unsupported service "%s".' % service)
- ServiceHandlerFactory = getattr(mapnikmodule.ogcserver, service).ServiceHandlerFactory
- servicehandler = ServiceHandlerFactory(self.conf, self.mapfactory, onlineresource, reqparams.get('version', None))
- if reqparams.has_key('version'):
- del reqparams['version']
- if request not in servicehandler.SERVICE_PARAMS.keys():
- raise OGCException('Operation "%s" not supported.' % request, 'OperationNotSupported')
-
- # Get parameters and pass to WMSFactory in custom "setup" method
- ogcparams = servicehandler.processParameters(request, reqparams)
- try:
- requesthandler = getattr(servicehandler, request)
- except:
- raise OGCException('Operation "%s" not supported.' % request, 'OperationNotSupported')
-
- response = requesthandler(ogcparams)
- apacheReq.content_type = response.content_type
- apacheReq.status = apache.HTTP_OK
- except Exception, E:
- return self.traceback(apacheReq,E)
-
- if self.max_age:
- apacheReq.headers_out.add('Cache-Control', max_age)
- apacheReq.headers_out.add('Content-Length', str(len(response.content)))
- apacheReq.send_http_header()
- apacheReq.write(response.content)
- return apache.OK
-
- def traceback(self, apacheReq,E):
- reqparams = lowerparams(util.FieldStorage(apacheReq))
- version = reqparams.get('version', None)
- if not version:
- version = Version('1.3.0')
- else:
- version = Version(version)
- if version >= '1.3.0':
- eh = ExceptionHandler130(self.debug)
- else:
- eh = ExceptionHandler111(self.debug)
- response = eh.getresponse(reqparams)
- apacheReq.content_type = response.content_type
- apacheReq.headers_out.add('Content-Length', str(len(response.content)))
- apacheReq.send_http_header()
- apacheReq.write(response.content)
- return apache.OK
-
-def lowerparams(params):
- reqparams = {}
- for key, value in params.items():
- reqparams[key.lower()] = value
- return reqparams
diff --git a/bindings/python/mapnik/ogcserver/wms111.py b/bindings/python/mapnik/ogcserver/wms111.py
deleted file mode 100644
index 62d44ec2d..000000000
--- a/bindings/python/mapnik/ogcserver/wms111.py
+++ /dev/null
@@ -1,238 +0,0 @@
-#
-# This file is part of Mapnik (c++ mapping toolkit)
-#
-# Copyright (C) 2006 Jean-Francois Doyon
-#
-# Mapnik is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-#
-# $Id$
-
-"""WMS 1.1.1 compliant GetCapabilities, GetMap, GetFeatureInfo, and Exceptions interface."""
-
-from common import ParameterDefinition, Response, Version, ListFactory, \
- ColorFactory, CRSFactory, WMSBaseServiceHandler, CRS, \
- BaseExceptionHandler, Projection
-from exceptions import OGCException, ServerConfigurationError
-from mapnik import Coord
-
-try:
- from lxml import etree as ElementTree
-except ImportError:
- import xml.etree.ElementTree as ElementTree
-except ImportError:
- import elementtree.ElementTree as ElementTree
-
-class ServiceHandler(WMSBaseServiceHandler):
-
- SERVICE_PARAMS = {
- 'GetCapabilities': {
- 'updatesequence': ParameterDefinition(False, str)
- },
- 'GetMap': {
- 'layers': ParameterDefinition(True, ListFactory(str)),
- 'styles': ParameterDefinition(True, ListFactory(str)),
- 'srs': ParameterDefinition(True, CRSFactory(['EPSG'])),
- 'bbox': ParameterDefinition(True, ListFactory(float)),
- 'width': ParameterDefinition(True, int),
- 'height': ParameterDefinition(True, int),
- 'format': ParameterDefinition(True, str, allowedvalues=('image/png', 'image/jpeg')),
- 'transparent': ParameterDefinition(False, str, 'FALSE', ('TRUE', 'FALSE')),
- 'bgcolor': ParameterDefinition(False, ColorFactory, ColorFactory('0xFFFFFF')),
- 'exceptions': ParameterDefinition(False, str, 'application/vnd.ogc.se_xml', ('application/vnd.ogc.se_xml', 'application/vnd.ogc.se_inimage', 'application/vnd.ogc.se_blank','text/html'))
- },
- 'GetFeatureInfo': {
- 'layers': ParameterDefinition(True, ListFactory(str)),
- 'styles': ParameterDefinition(False, ListFactory(str)),
- 'srs': ParameterDefinition(True, CRSFactory(['EPSG'])),
- 'bbox': ParameterDefinition(True, ListFactory(float)),
- 'width': ParameterDefinition(True, int),
- 'height': ParameterDefinition(True, int),
- 'format': ParameterDefinition(False, str, allowedvalues=('image/png', 'image/jpeg')),
- 'transparent': ParameterDefinition(False, str, 'FALSE', ('TRUE', 'FALSE')),
- 'bgcolor': ParameterDefinition(False, ColorFactory, ColorFactory('0xFFFFFF')),
- 'exceptions': ParameterDefinition(False, str, 'application/vnd.ogc.se_xml', ('application/vnd.ogc.se_xml', 'application/vnd.ogc.se_inimage', 'application/vnd.ogc.se_blank','text/html')),
- 'query_layers': ParameterDefinition(True, ListFactory(str)),
- 'info_format': ParameterDefinition(True, str, allowedvalues=('text/plain', 'text/xml')),
- 'feature_count': ParameterDefinition(False, int, 1),
- 'x': ParameterDefinition(True, int),
- 'y': ParameterDefinition(True, int)
- }
- }
-
- CONF_SERVICE = [
- ['title', 'Title', str],
- ['abstract', 'Abstract', str],
- ['onlineresource', 'OnlineResource', str],
- ['fees', 'Fees', str],
- ['accessconstraints', 'AccessConstraints', str],
- ['keywordlist', 'KeywordList', str]
- ]
-
- capabilitiesxmltemplate = """
-
-
-
- WMS
-
-
-
-
- application/vnd.ogc.wms_xml
-
-
-
-
-
-
-
-
-
- image/png
- image/jpeg
-
-
-
-
-
-
-
-
-
- text/plain
-
-
-
-
-
-
-
-
-
-
- application/vnd.ogc.se_xml
- application/vnd.ogc.se_inimage
- application/vnd.ogc.se_blank
-
-
- A Mapnik WMS Server
- A Mapnik WMS Server
-
-
-
- """
-
- def __init__(self, conf, mapfactory, opsonlineresource):
- self.conf = conf
- self.mapfactory = mapfactory
- self.opsonlineresource = opsonlineresource
- if self.conf.has_option('service', 'allowedepsgcodes'):
- self.allowedepsgcodes = map(lambda code: 'epsg:%s' % code, self.conf.get('service', 'allowedepsgcodes').split(','))
- else:
- raise ServerConfigurationError('Allowed EPSG codes not properly configured.')
- self.capabilities = None
-
- def GetCapabilities(self, params):
- if not self.capabilities:
- capetree = ElementTree.fromstring(self.capabilitiesxmltemplate)
-
- elements = capetree.findall('Capability//OnlineResource')
- for element in elements:
- element.set('{http://www.w3.org/1999/xlink}href', self.opsonlineresource)
-
- self.processServiceCapabilities(capetree)
-
- rootlayerelem = capetree.find('{http://www.opengis.net/wms}Capability/{http://www.opengis.net/wms}Layer')
-
- for epsgcode in self.allowedepsgcodes:
- rootlayercrs = ElementTree.Element('SRS')
- rootlayercrs.text = epsgcode.upper()
- rootlayerelem.append(rootlayercrs)
-
- for layer in self.mapfactory.ordered_layers:
- layerproj = Projection(layer.srs)
- layername = ElementTree.Element('Name')
- layername.text = layer.name
- env = layer.envelope()
- llp = layerproj.inverse(Coord(env.minx, env.miny))
- urp = layerproj.inverse(Coord(env.maxx, env.maxy))
- latlonbb = ElementTree.Element('LatLonBoundingBox')
- latlonbb.set('minx', str(llp.x))
- latlonbb.set('miny', str(llp.y))
- latlonbb.set('maxx', str(urp.x))
- latlonbb.set('maxy', str(urp.y))
- layerbbox = ElementTree.Element('BoundingBox')
- layerbbox.set('SRS', layerproj.epsgstring())
- layerbbox.set('minx', str(env.minx))
- layerbbox.set('miny', str(env.miny))
- layerbbox.set('maxx', str(env.maxx))
- layerbbox.set('maxy', str(env.maxy))
- layere = ElementTree.Element('Layer')
- layere.append(layername)
- if layer.title:
- layertitle = ElementTree.Element('Title')
- layertitle.text = layer.title
- layere.append(layertitle)
- if layer.abstract:
- layerabstract = ElementTree.Element('Abstract')
- layerabstract.text = layer.abstract
- layere.append(layerabstract)
- if layer.queryable:
- layere.set('queryable', '1')
- layere.append(latlonbb)
- layere.append(layerbbox)
- if len(layer.wmsextrastyles) > 0:
- for extrastyle in [layer.wmsdefaultstyle] + list(layer.wmsextrastyles):
- style = ElementTree.Element('Style')
- stylename = ElementTree.Element('Name')
- stylename.text = extrastyle
- styletitle = ElementTree.Element('Title')
- styletitle.text = extrastyle
- style.append(stylename)
- style.append(styletitle)
- layere.append(style)
- rootlayerelem.append(layere)
- self.capabilities = '\n' + ElementTree.tostring(capetree)
- response = Response('application/vnd.ogc.wms_xml', self.capabilities)
- return response
-
- def GetMap(self, params):
- params['crs'] = params['srs']
- return WMSBaseServiceHandler.GetMap(self, params)
-
- def GetFeatureInfo(self, params):
- params['crs'] = params['srs']
- params['i'] = params['x']
- params['j'] = params['y']
- return WMSBaseServiceHandler.GetFeatureInfo(self, params, 'query_map_point')
-
-class ExceptionHandler(BaseExceptionHandler):
-
- xmlmimetype = "application/vnd.ogc.se_xml"
-
- xmltemplate = ElementTree.fromstring("""
-
-
-
-
- """)
-
- xpath = 'ServiceException'
-
- handlers = {'application/vnd.ogc.se_xml': BaseExceptionHandler.xmlhandler,
- 'application/vnd.ogc.se_inimage': BaseExceptionHandler.inimagehandler,
- 'application/vnd.ogc.se_blank': BaseExceptionHandler.blankhandler,
- 'text/html': BaseExceptionHandler.htmlhandler}
-
- defaulthandler = 'application/vnd.ogc.se_xml'
diff --git a/bindings/python/mapnik/ogcserver/wms130.py b/bindings/python/mapnik/ogcserver/wms130.py
deleted file mode 100644
index 609da66b3..000000000
--- a/bindings/python/mapnik/ogcserver/wms130.py
+++ /dev/null
@@ -1,264 +0,0 @@
-#
-# This file is part of Mapnik (c++ mapping toolkit)
-#
-# Copyright (C) 2006 Jean-Francois Doyon
-#
-# Mapnik is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-#
-# $Id$
-
-"""WMS 1.3.0 compliant GetCapabilities, GetMap, GetFeatureInfo, and Exceptions interface."""
-
-from common import ParameterDefinition, Response, Version, ListFactory, \
- ColorFactory, CRSFactory, CRS, WMSBaseServiceHandler, \
- BaseExceptionHandler, Projection, Box2d
-from exceptions import OGCException, ServerConfigurationError
-from mapnik import Coord
-
-try:
- from lxml import etree as ElementTree
-except ImportError:
- import xml.etree.ElementTree as ElementTree
-except ImportError:
- import elementtree.ElementTree as ElementTree
-
-class ServiceHandler(WMSBaseServiceHandler):
-
- SERVICE_PARAMS = {
- 'GetCapabilities': {
- 'format': ParameterDefinition(False, str, 'text/xml', ('text/xml',), True),
- 'updatesequence': ParameterDefinition(False, str)
- },
- 'GetMap': {
- 'layers': ParameterDefinition(True, ListFactory(str)),
- 'styles': ParameterDefinition(True, ListFactory(str)),
- 'crs': ParameterDefinition(True, CRSFactory(['EPSG'])),
- 'bbox': ParameterDefinition(True, ListFactory(float)),
- 'width': ParameterDefinition(True, int),
- 'height': ParameterDefinition(True, int),
- 'format': ParameterDefinition(True, str, allowedvalues=('image/png', 'image/jpeg')),
- 'transparent': ParameterDefinition(False, str, 'FALSE', ('TRUE', 'FALSE')),
- 'bgcolor': ParameterDefinition(False, ColorFactory, ColorFactory('0xFFFFFF')),
- 'exceptions': ParameterDefinition(False, str, 'XML', ('XML', 'INIMAGE', 'BLANK','HTML')),
- },
- 'GetFeatureInfo': {
- 'layers': ParameterDefinition(True, ListFactory(str)),
- 'styles': ParameterDefinition(False, ListFactory(str)),
- 'crs': ParameterDefinition(True, CRSFactory(['EPSG'])),
- 'bbox': ParameterDefinition(True, ListFactory(float)),
- 'width': ParameterDefinition(True, int),
- 'height': ParameterDefinition(True, int),
- 'format': ParameterDefinition(False, str, allowedvalues=('image/png', 'image/jpeg')),
- 'transparent': ParameterDefinition(False, str, 'FALSE', ('TRUE', 'FALSE')),
- 'bgcolor': ParameterDefinition(False, ColorFactory, ColorFactory('0xFFFFFF')),
- 'exceptions': ParameterDefinition(False, str, 'XML', ('XML', 'INIMAGE', 'BLANK','HTML')),
- 'query_layers': ParameterDefinition(True, ListFactory(str)),
- 'info_format': ParameterDefinition(True, str, allowedvalues=('text/plain', 'text/xml')),
- 'feature_count': ParameterDefinition(False, int, 1),
- 'i': ParameterDefinition(True, float),
- 'j': ParameterDefinition(True, float)
- }
- }
-
- CONF_SERVICE = [
- ['title', 'Title', str],
- ['abstract', 'Abstract', str],
- ['onlineresource', 'OnlineResource', str],
- ['fees', 'Fees', str],
- ['accessconstraints', 'AccessConstraints', str],
- ['layerlimit', 'LayerLimit', int],
- ['maxwidth', 'MaxWidth', int],
- ['maxheight', 'MaxHeight', int],
- ['keywordlist', 'KeywordList', str]
- ]
-
- capabilitiesxmltemplate = """
-
-
- WMS
-
-
-
-
- text/xml
-
-
-
-
-
-
-
-
-
- image/png
- image/jpeg
-
-
-
-
-
-
-
-
-
- text/plain
-
-
-
-
-
-
-
-
-
-
- XML
- INIMAGE
- BLANK
-
-
- A Mapnik WMS Server
- A Mapnik WMS Server
-
-
-
- """
-
- def __init__(self, conf, mapfactory, opsonlineresource):
- self.conf = conf
- self.mapfactory = mapfactory
- self.opsonlineresource = opsonlineresource
- if self.conf.has_option('service', 'allowedepsgcodes'):
- self.allowedepsgcodes = map(lambda code: 'epsg:%s' % code, self.conf.get('service', 'allowedepsgcodes').split(','))
- else:
- raise ServerConfigurationError('Allowed EPSG codes not properly configured.')
- self.capabilities = None
-
- def GetCapabilities(self, params):
- if not self.capabilities:
- capetree = ElementTree.fromstring(self.capabilitiesxmltemplate)
-
- elements = capetree.findall('{http://www.opengis.net/wms}Capability//{http://www.opengis.net/wms}OnlineResource')
- for element in elements:
- element.set('{http://www.w3.org/1999/xlink}href', self.opsonlineresource)
-
- self.processServiceCapabilities(capetree)
-
- rootlayerelem = capetree.find('{http://www.opengis.net/wms}Capability/{http://www.opengis.net/wms}Layer')
-
- for epsgcode in self.allowedepsgcodes:
- rootlayercrs = ElementTree.Element('CRS')
- rootlayercrs.text = epsgcode.upper()
- rootlayerelem.append(rootlayercrs)
-
- for layer in self.mapfactory.ordered_layers:
- layerproj = Projection(layer.srs)
- layername = ElementTree.Element('Name')
- layername.text = layer.name
- env = layer.envelope()
- layerexgbb = ElementTree.Element('EX_GeographicBoundingBox')
- ll = layerproj.inverse(Coord(env.minx, env.miny))
- ur = layerproj.inverse(Coord(env.maxx, env.maxy))
- exgbb_wbl = ElementTree.Element('westBoundLongitude')
- exgbb_wbl.text = str(ll.x)
- layerexgbb.append(exgbb_wbl)
- exgbb_ebl = ElementTree.Element('eastBoundLongitude')
- exgbb_ebl.text = str(ur.x)
- layerexgbb.append(exgbb_ebl)
- exgbb_sbl = ElementTree.Element('southBoundLatitude')
- exgbb_sbl.text = str(ll.y)
- layerexgbb.append(exgbb_sbl)
- exgbb_nbl = ElementTree.Element('northBoundLatitude')
- exgbb_nbl.text = str(ur.y)
- layerexgbb.append(exgbb_nbl)
- layerbbox = ElementTree.Element('BoundingBox')
- layerbbox.set('CRS', layerproj.epsgstring())
- layerbbox.set('minx', str(env.minx))
- layerbbox.set('miny', str(env.miny))
- layerbbox.set('maxx', str(env.maxx))
- layerbbox.set('maxy', str(env.maxy))
- layere = ElementTree.Element('Layer')
- layere.append(layername)
- if layer.title:
- layertitle = ElementTree.Element('Title')
- layertitle.text = layer.title
- layere.append(layertitle)
- if layer.abstract:
- layerabstract = ElementTree.Element('Abstract')
- layerabstract.text = layer.abstract
- layere.append(layerabstract)
- if layer.queryable:
- layere.set('queryable', '1')
- layere.append(layerexgbb)
- layere.append(layerbbox)
- if len(layer.wmsextrastyles) > 0:
- for extrastyle in [layer.wmsdefaultstyle] + list(layer.wmsextrastyles):
- style = ElementTree.Element('Style')
- stylename = ElementTree.Element('Name')
- stylename.text = extrastyle
- styletitle = ElementTree.Element('Title')
- styletitle.text = extrastyle
- style.append(stylename)
- style.append(styletitle)
- layere.append(style)
- rootlayerelem.append(layere)
- self.capabilities = '' + ElementTree.tostring(capetree)
- response = Response('text/xml', self.capabilities)
- return response
-
- def GetMap(self, params):
- if params['width'] > int(self.conf.get('service', 'maxwidth')) or params['height'] > int(self.conf.get('service', 'maxheight')):
- raise OGCException('Requested map size exceeds limits set by this server.')
- return WMSBaseServiceHandler.GetMap(self, params)
-
- def _buildMap(self, params):
- """ Override _buildMap method to handle reverse axis ordering in WMS 1.3.0.
-
- More info: http://mapserver.org/development/rfc/ms-rfc-30.html
-
- 'when using epsg code >=4000 and <5000 will be assumed to have a reversed axes.'
-
- """
- # Call superclass method
- m = WMSBaseServiceHandler._buildMap(self, params)
- # for range of epsg codes reverse axis
- if params['crs'].code >= 4000 and params['crs'].code < 5000:
- m.zoom_to_box(Box2d(params['bbox'][1], params['bbox'][0], params['bbox'][3], params['bbox'][2]))
- return m
-
-class ExceptionHandler(BaseExceptionHandler):
-
- xmlmimetype = "text/xml"
-
- xmltemplate = ElementTree.fromstring("""
-
-
-
- """)
-
- xpath = '{http://www.opengis.net/ogc}ServiceException'
-
- handlers = {'XML': BaseExceptionHandler.xmlhandler,
- 'INIMAGE': BaseExceptionHandler.inimagehandler,
- 'BLANK': BaseExceptionHandler.blankhandler,
- 'HTML': BaseExceptionHandler.htmlhandler}
-
- defaulthandler = 'XML'
diff --git a/bindings/python/mapnik/ogcserver/wsgi.py b/bindings/python/mapnik/ogcserver/wsgi.py
deleted file mode 100644
index 66ba6ed10..000000000
--- a/bindings/python/mapnik/ogcserver/wsgi.py
+++ /dev/null
@@ -1,106 +0,0 @@
-#
-# This file is part of Mapnik (c++ mapping toolkit)
-#
-# Copyright (C) 2006 Jean-Francois Doyon
-#
-# Mapnik is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-#
-# $Id$
-
-"""WSGI application wrapper for Mapnik OGC WMS Server."""
-
-from exceptions import OGCException, ServerConfigurationError
-from configparser import SafeConfigParser
-from cgi import parse_qs
-from wms111 import ExceptionHandler as ExceptionHandler111
-from wms130 import ExceptionHandler as ExceptionHandler130
-from common import Version
-
-class WSGIApp:
-
- def __init__(self, configpath):
- conf = SafeConfigParser()
- conf.readfp(open(configpath))
- self.conf = conf
- if not conf.has_option_with_value('server', 'module'):
- raise ServerConfigurationError('The factory module is not defined in the configuration file.')
- try:
- mapfactorymodule = __import__(conf.get('server', 'module'))
- except ImportError:
- raise ServerConfigurationError('The factory module could not be loaded.')
- if hasattr(mapfactorymodule, 'WMSFactory'):
- self.mapfactory = getattr(mapfactorymodule, 'WMSFactory')()
- else:
- raise ServerConfigurationError('The factory module does not have a WMSFactory class.')
- if conf.has_option('server', 'debug'):
- self.debug = int(conf.get('server', 'debug'))
- else:
- self.debug = 0
- if self.conf.has_option_with_value('server', 'maxage'):
- self.max_age = 'max-age=%d' % self.conf.get('server', 'maxage')
- else:
- self.max_age = None
-
- def __call__(self, environ, start_response):
- reqparams = {}
- for key, value in parse_qs(environ['QUERY_STRING'], True).items():
- reqparams[key.lower()] = value[0]
- onlineresource = 'http://%s:%s%s?' % (environ['SERVER_NAME'], environ['SERVER_PORT'], environ['PATH_INFO'])
- try:
- if not reqparams.has_key('request'):
- raise OGCException('Missing request parameter.')
- request = reqparams['request']
- del reqparams['request']
- if request == 'GetCapabilities' and not reqparams.has_key('service'):
- raise OGCException('Missing service parameter.')
- if request in ['GetMap', 'GetFeatureInfo']:
- service = 'WMS'
- else:
- service = reqparams['service']
- if reqparams.has_key('service'):
- del reqparams['service']
- try:
- mapnikmodule = __import__('mapnik.ogcserver.' + service)
- except:
- raise OGCException('Unsupported service "%s".' % service)
- ServiceHandlerFactory = getattr(mapnikmodule.ogcserver, service).ServiceHandlerFactory
- servicehandler = ServiceHandlerFactory(self.conf, self.mapfactory, onlineresource, reqparams.get('version', None))
- if reqparams.has_key('version'):
- del reqparams['version']
- if request not in servicehandler.SERVICE_PARAMS.keys():
- raise OGCException('Operation "%s" not supported.' % request, 'OperationNotSupported')
- ogcparams = servicehandler.processParameters(request, reqparams)
- try:
- requesthandler = getattr(servicehandler, request)
- except:
- raise OGCException('Operation "%s" not supported.' % request, 'OperationNotSupported')
- response = requesthandler(ogcparams)
- except:
- version = reqparams.get('version', None)
- if not version:
- version = Version('1.3.0')
- else:
- version = Version(version)
- if version >= '1.3.0':
- eh = ExceptionHandler130(self.debug)
- else:
- eh = ExceptionHandler111(self.debug)
- response = eh.getresponse(reqparams)
- response_headers = [('Content-Type', response.content_type),('Content-Length', str(len(response.content)))]
- if self.max_age:
- response_headers.append(('Cache-Control', max_age))
- start_response('200 OK', response_headers)
- yield response.content
-