OWS.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  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 self.service == "WFS":
  63. if "version" in params:
  64. params["version"] = "1.0.0"
  65. else:
  66. params["VERSION"] = "1.0.0"
  67. url = urlparse.urlunparse((self.parsedUrl[0],
  68. self.parsedUrl[1],
  69. self.parsedUrl[2],
  70. self.parsedUrl[3],
  71. urllib.unquote(urllib.urlencode(params,True)),
  72. self.parsedUrl[5]))
  73. e = objectify.parse(urllib.urlopen(url))
  74. self.capabilities = e.getroot()
  75. try:
  76. params.pop("service")
  77. except:
  78. pass
  79. try:
  80. params.pop("request")
  81. except:
  82. pass
  83. try:
  84. params.pop("SERVICE")
  85. except:
  86. pass
  87. try:
  88. params.pop("REQUEST")
  89. except:
  90. pass
  91. self.url = urlparse.urlunparse((self.parsedUrl[0],
  92. self.parsedUrl[1],
  93. self.parsedUrl[2],
  94. self.parsedUrl[3],
  95. urllib.urlencode(params,True),
  96. self.parsedUrl[5]))
  97. def getParams(self):
  98. return urlparse.parse_qs(self.qstring)
  99. def getOnlineResource(self,onlineresource,mapfilename=None):
  100. o = urlparse.urlparse(onlineresource)
  101. params = urlparse.parse_qs(o.query,keep_blank_values=True)
  102. params["owsUrl"] = self.url
  103. params["owsService"] = self.service
  104. params["map"] = self.getMapfileLocation(mapfilename)
  105. location = urlparse.urlunparse((o[0],o[1],o[2],o[3],urllib.urlencode(params,True),o[5]))
  106. logging.debug("Setting OnlineResource to %s"% location)
  107. return location
  108. def getMapfileLocation(self,mapfilename=None):
  109. # save the map if possible
  110. if mapfilename:
  111. mapfilename.replace("..","") # remove potential path change
  112. # mapfile must end with .map and cachedir must be at the
  113. # beginning of the mapfile name
  114. if mapfilename.endswith(".map") and \
  115. mapfilename.find(self.cachedir) == 0:
  116. return mapfilename
  117. else:
  118. # do not save anything
  119. return
  120. # save to new location otherwice
  121. else:
  122. return os.path.join(self.cachedir,self.mapfileName)
  123. def __getCacheDir(self):
  124. self.cachedir = tempfile.mkdtemp(prefix="%s-%s"%(self.service,
  125. md5.new(self.url).hexdigest()),
  126. dir=self.config.get("OWSViewer","cachedir"))
  127. os.chmod(self.cachedir, 0777)
  128. logging.debug("Cachedir %s created" % self.cachedir)
  129. open(os.path.join(self.cachedir,"url.txt"),"w").write(self.url)
  130. return self.cachedir
  131. def performRequest(self):
  132. request = mapscript.OWSRequest()
  133. request.loadParams()
  134. mapobj = None
  135. self.request=request.getValueByName("REQUEST")
  136. # if no 'map' parameter in URL, create new mapfile
  137. if not request.getValueByName("map"):
  138. mapobj = self.makeMap()
  139. else:
  140. # there is 'map' parameter in URL and the file exists, load it
  141. if os.path.isfile(request.getValueByName("map")):
  142. mapobj = mapscript.mapObj(request.getValueByName("map"))
  143. # there is 'map' parameter in URL BUT the file does not exist:
  144. # create
  145. else:
  146. mapobj = self.makeMap(request.getValueByName("map"))
  147. mapobj.OWSDispatch(request)
  148. def getMapObj(self,mapfilename=None):
  149. self.__getCacheDir()
  150. if self.url is not None and self.capabilities is None:
  151. self.__getCapabilities()
  152. mapobj = mapscript.mapObj()
  153. mapobj.setMetaData("wms_onlineresource",self.getOnlineResource(self.config.get("MapServer","onlineresource"),mapfilename))
  154. logging.debug("Setting SRS to %s"%self.config.get("MapServer","srs"))
  155. mapobj.setMetaData("wms_srs",self.config.get("MapServer","srs"))
  156. mapobj.setProjection("init=epsg:4326")
  157. mapobj.setSize(500,500)
  158. mapobj.setExtent(-180,-90,90,180)
  159. logging.debug("Setting ERRORFILE to %s"%self.config.get("MapServer","errorfile"))
  160. if os.access(self.config.get("MapServer","errorfile"), os.W_OK):
  161. mapobj.setConfigOption("MS_ERRORFILE",self.config.get("MapServer","errorfile"))
  162. else:
  163. logging.warning("Cannot set ERRORFILE to %s: %s "%\
  164. (self.config.get("MapServer","errorfile"),"Write access denided"))
  165. logging.debug("Setting IMAGEPATH to %s"%self.config.get("MapServer","imagepath"))
  166. mapobj.web.imagepath=self.config.get("MapServer","imagepath")
  167. mapobj.setMetaData("ows_enable_request","*")
  168. return mapobj
  169. def saveMapfile(self,mapobj,mapfilename):
  170. self.mapfilename = self.getMapfileLocation(mapfilename)
  171. if self.mapfilename:
  172. # save mapfile ONLY if GetCapabilities requested - it makes no
  173. # sense for other cases
  174. logging.info("Saving mapfile to %s" % self.mapfilename)
  175. mapobj.save(self.mapfilename)
  176. else:
  177. logging.info("Mapfile NOT saved")
  178. return self.mapfilename
  179. def getLayerUrl(self):
  180. layerurl = self.url
  181. if self.url.find("?") > -1:
  182. if not self.url.endswith("?") and\
  183. not self.url.endswith("&"):
  184. layerurl += "&"
  185. else:
  186. layerurl += "?"
  187. return layerurl
  188. def createLayerDefinitionFile(self, name, templatefile):
  189. layerurl = self.getLayerUrl()
  190. defFileName = os.path.join(self.cachedir,'%s.%s'%(name,self.service.lower()))
  191. open(defFileName,'w').write(
  192. Template(open(templatefile).read()).substitute(
  193. dict(url= layerurl, name=name)))
  194. logging.debug("Created %s layer definition file" % defFileName)
  195. return defFileName
  196. def getService():
  197. qstring = os.environ["QUERY_STRING"]
  198. params = urlparse.parse_qs(qstring)
  199. owsUrl = urllib.unquote(params["owsUrl"][0])
  200. if params["owsService"][0].lower() == "wfs":
  201. from wfs import WFS
  202. return WFS(owsUrl,qstring)
  203. elif params["owsService"][0].lower() == "wcs":
  204. from wcs import WCS
  205. return WCS(owsUrl,qstring)