OWS.py 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. #!/usr/bin/env python
  2. # coding=utf-8
  3. import urlparse
  4. import urllib
  5. from lxml import objectify
  6. import os,sys
  7. import tempfile
  8. import logging
  9. import ConfigParser
  10. import md5
  11. import mapscript
  12. from string import Template
  13. class OWS:
  14. capabilities = None
  15. url = None
  16. requestUrl = None
  17. mapobj = None
  18. qstring = None
  19. owsns11 = "http://www.opengis.net/ows/1.1"
  20. owsns = "http://www.opengis.net/ows"
  21. cachedir = None
  22. mapfileName = "mapfile.map"
  23. config = None
  24. parsedUrl = None
  25. service = None
  26. mapfilename = None
  27. def __init__(self,url=None,qstring=None,configFile=None):
  28. self.requestUrl = url
  29. if url:
  30. self.url = url
  31. self.__getCapabilities()
  32. if qstring:
  33. self.qstring = qstring
  34. configFiles = [
  35. os.path.join(os.path.dirname(__file__),"config.cfg")
  36. ]
  37. if sys.platform == "win32":
  38. pass # TODO Default conf. file on windows platform
  39. elif sys.platform == "linux2":
  40. configFiles.append("/etc/owsviewer.cfg")
  41. if configFile:
  42. configFiles.append(configFile)
  43. self.config = ConfigParser.ConfigParser()
  44. self.config.read(configFiles)
  45. logging.debug("Creating cachedir for %s in %s" % (self.url,self.config.get("OWSViewer","cachedir")))
  46. logging.debug("%s initialized"%self.service)
  47. def __getCapabilities(self):
  48. self.parsedUrl = urlparse.urlparse(self.url)
  49. params = urlparse.parse_qs(self.parsedUrl.query,keep_blank_values=True)
  50. if "request" in params:
  51. params["request"] = "GetCapabilities"
  52. else:
  53. params["REQUEST"] = "GetCapabilities"
  54. if "service" in params:
  55. params["service"] = self.service
  56. else:
  57. params["SERVICE"] = self.service
  58. # HACK HACK HACK
  59. # 1.0.0 works
  60. # 1.1.0 reverses axes, while OGR is requesting the FeatureType
  61. # using BBOX FILTER
  62. if "version" in params:
  63. params["version"] = "1.0.0"
  64. else:
  65. params["VERSION"] = "1.0.0"
  66. url = urlparse.urlunparse((self.parsedUrl[0],
  67. self.parsedUrl[1],
  68. self.parsedUrl[2],
  69. self.parsedUrl[3],
  70. urllib.unquote(urllib.urlencode(params,True)),
  71. self.parsedUrl[5]))
  72. e = objectify.parse(urllib.urlopen(url))
  73. self.capabilities = e.getroot()
  74. try:
  75. params.pop("service")
  76. except:
  77. pass
  78. try:
  79. params.pop("request")
  80. except:
  81. pass
  82. try:
  83. params.pop("SERVICE")
  84. except:
  85. pass
  86. try:
  87. params.pop("REQUEST")
  88. except:
  89. pass
  90. self.url = urlparse.urlunparse((self.parsedUrl[0],
  91. self.parsedUrl[1],
  92. self.parsedUrl[2],
  93. self.parsedUrl[3],
  94. urllib.urlencode(params,True),
  95. self.parsedUrl[5]))
  96. def getParams(self):
  97. return urlparse.parse_qs(self.qstring)
  98. def getOnlineResource(self,onlineresource,mapfilename=None):
  99. o = urlparse.urlparse(onlineresource)
  100. params = urlparse.parse_qs(o.query,keep_blank_values=True)
  101. params["owsUrl"] = self.url
  102. params["owsService"] = self.service
  103. params["map"] = self.getMapfileLocation(mapfilename)
  104. location = urlparse.urlunparse((o[0],o[1],o[2],o[3],urllib.urlencode(params,True),o[5]))
  105. logging.debug("Setting OnlineResource to %s"% location)
  106. return location
  107. def getMapfileLocation(self,mapfilename=None):
  108. # save the map if possible
  109. if mapfilename:
  110. mapfilename.replace("..","") # remove potential path change
  111. # mapfile must end with .map and cachedir must be at the
  112. # beginning of the mapfile name
  113. if mapfilename.endswith(".map") and \
  114. mapfilename.find(self.cachedir) == 0:
  115. return mapfilename
  116. else:
  117. # do not save anything
  118. return
  119. # save to new location otherwice
  120. else:
  121. return os.path.join(self.cachedir,self.mapfileName)
  122. def __getCacheDir(self):
  123. self.cachedir = tempfile.mkdtemp(prefix="%s-%s"%(self.service,
  124. md5.new(self.url).hexdigest()),
  125. dir=self.config.get("OWSViewer","cachedir"))
  126. os.chmod(self.cachedir, 0777)
  127. logging.debug("Cachedir %s created" % self.cachedir)
  128. open(os.path.join(self.cachedir,"url.txt"),"w").write(self.url)
  129. return self.cachedir
  130. def performRequest(self):
  131. request = mapscript.OWSRequest()
  132. request.loadParams()
  133. mapobj = None
  134. self.request=request.getValueByName("REQUEST")
  135. # if no 'map' parameter in URL, create new mapfile
  136. if not request.getValueByName("map"):
  137. mapobj = self.makeMap()
  138. else:
  139. # there is 'map' parameter in URL and the file exists, load it
  140. if os.path.isfile(request.getValueByName("map")):
  141. mapobj = mapscript.mapObj(request.getValueByName("map"))
  142. # there is 'map' parameter in URL BUT the file does not exist:
  143. # create
  144. else:
  145. mapobj = self.makeMap(request.getValueByName("map"))
  146. mapobj.OWSDispatch(request)
  147. def getMapObj(self,mapfilename=None):
  148. self.__getCacheDir()
  149. if self.url is not None and self.capabilities is None:
  150. self.__getCapabilities()
  151. mapobj = mapscript.mapObj()
  152. mapobj.setMetaData("wms_onlineresource",self.getOnlineResource(self.config.get("MapServer","onlineresource"),mapfilename))
  153. logging.debug("Setting SRS to %s"%self.config.get("MapServer","srs"))
  154. mapobj.setMetaData("wms_srs",self.config.get("MapServer","srs"))
  155. mapobj.setProjection("init=epsg:4326")
  156. mapobj.setSize(500,500)
  157. mapobj.setExtent(-180,-90,90,180)
  158. logging.debug("Setting ERRORFILE to %s"%self.config.get("MapServer","errorfile"))
  159. if os.access(self.config.get("MapServer","errorfile"), os.W_OK):
  160. mapobj.setConfigOption("MS_ERRORFILE",self.config.get("MapServer","errorfile"))
  161. else:
  162. logging.warning("Cannot set ERRORFILE to %s: %s "%\
  163. (self.config.get("MapServer","errorfile"),"Write access denided"))
  164. logging.debug("Setting IMAGEPATH to %s"%self.config.get("MapServer","imagepath"))
  165. mapobj.web.imagepath=self.config.get("MapServer","imagepath")
  166. mapobj.setMetaData("ows_enable_request","*")
  167. return mapobj
  168. def saveMapfile(self,mapobj,mapfilename):
  169. self.mapfilename = self.getMapfileLocation(mapfilename)
  170. if self.mapfilename:
  171. # save mapfile ONLY if GetCapabilities requested - it makes no
  172. # sense for other cases
  173. logging.info("Saving mapfile to %s" % self.mapfilename)
  174. mapobj.save(self.mapfilename)
  175. else:
  176. logging.info("Mapfile NOT saved")
  177. return self.mapfilename
  178. def getLayerUrl(self):
  179. layerurl = self.url
  180. if self.url.find("?") > -1:
  181. if not self.url.endswith("?") and\
  182. not self.url.endswith("&"):
  183. layerurl += "&"
  184. else:
  185. layerurl += "?"
  186. return layerurl
  187. def createLayerDefinitionFile(self, name, templatefile):
  188. layerurl = self.getLayerUrl()
  189. defFileName = os.path.join(self.cachedir,'%s.%s'%(name,self.service.lower()))
  190. open(defFileName,'w').write(
  191. Template(open(templatefile).read()).substitute(
  192. dict(url= layerurl, name=name)))
  193. logging.debug("Created %s layer definition file" % defFileName)
  194. return defFileName
  195. def getService():
  196. qstring = os.environ["QUERY_STRING"]
  197. params = urlparse.parse_qs(qstring)
  198. owsUrl = urllib.unquote(params["owsUrl"][0])
  199. if params["owsService"][0].lower() == "wfs":
  200. from wfs import WFS
  201. return WFS(owsUrl,qstring)
  202. elif params["owsService"][0].lower() == "wcs":
  203. from wcs import WCS
  204. return WCS(owsUrl,qstring)