#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # MapServer REST API is a python wrapper around MapServer which # # allows to manipulate a mapfile in a RESTFul way. It has been # # developped to match as close as possible the way the GeoServer # # REST API acts. # # # # Copyright (C) 2011-2013 Neogeo Technologies. # # # # This file is part of MapServer Rest API. # # # # MapServer Rest API is free software: you can redistribute it # # and/or modify it under the terms of the GNU General Public License # # as published by the Free Software Foundation, either version 3 of # # the License, or (at your option) any later version. # # # # MapServer Rest API 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 General Public License for more details. # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # import os import yaml import sys import mapfile import pyxml import webapp import xml.etree.ElementTree as etree from osgeo import osr __config = None def get_config(key=None, mode='r'): """This reads the YAML configuration file.""" global __config if not __config: try: __config = yaml.load(open(os.path.join(sys.path[0], 'mra.yaml'), mode)) except yaml.YAMLError, exc: exit('Error in configuration file: %s' % exc) return __config if key == None else __config[key] if key in __config else {} def get_mapfile_paths(): """Generates a list of mapfile paths managed by Mapserver REST API.""" for (root, subFolders, files) in os.walk(get_config('storage')['mapfiles']): for f in files: if f.endswith('.map') and not f.startswith('.'): yield os.path.join(root, f) def get_mapfile(name): with webapp.mightNotFound(message="Could not find mapfile '%s'." % name, exceptions=(IOError, OSError, KeyError)): mf = mapfile.Mapfile(name, get_config('storage')['mapfiles']) return mf def get_mapfile_workspace(mf_name, ws_name): mf = get_mapfile(mf_name) with webapp.mightNotFound("workspace", mapfile=mf_name): ws = mf.get_workspace(ws_name) return mf, ws def assert_is_empty(generator, tname, iname): try: next(generator) except StopIteration: pass # Everything is ok. else: raise webapp.Forbidden(message="Can't remove '%s' because it is an non-empty %s." % (iname, tname)) def href(url): return pyxml.Entries({'href': url}) def safe_path_join(root, *args): full_path = os.path.realpath(os.path.join(root, *args)) if not full_path.startswith(os.path.realpath(root)): raise webapp.Forbidden(message="path '%s' outside root directory." % (args)) return full_path def get_mapfile_path(*args): return safe_path_join(get_config('storage')['mapfiles'], *args) def get_resource_path(*args): return safe_path_join(get_config('storage')['resources'], *args) def get_st_data_path(ws_name, st_type, name, *args): return get_resource_path("workspaces", ws_name, st_type, name, *args) def get_ds_data_path(ws_name, name, *args): return get_st_data_path(ws_name, "datastores", name, *args) def get_cs_data_path(ws_name, name, *args): return get_st_data_path(ws_name, "coveragestores", name, *args) def get_style_path(name, *args): return safe_path_join(get_config('storage')['resources'], "styles", name, *args) def iter_styles(mapfile=None): """Generates a list of style paths managed by Mapserver REST API.""" used_styles = list(mapfile.iter_styles()) if mapfile else [] for s in used_styles: yield s styles_dir = os.path.join(get_config('storage')['resources'], "styles") if not os.path.isdir(styles_dir): return for (root, subFolders, files) in os.walk(styles_dir): for f in files: if f not in used_styles: yield f def mk_path(path): dirs = os.path.dirname(path) if not os.path.isdir(dirs): os.makedirs(dirs) def mk_mapfile_path(name, *args): path = get_mapfile_path(name, *args) mk_path(path) return path def mk_ds_data_path(ws_name, name, *args): path = get_ds_data_path(name, *args) mk_path(path) return path def mk_cs_data_path(ws_name, name, *args): path = get_cs_data_path(ws_name, name, *args) mk_path(path) return path def mk_st_data_path(ws_name, st_type, name, *args): path = get_st_data_path(ws_name, st_type, name, *args) mk_path(path) return path def mk_style_path(name, *args): path = get_style_path(name, *args) mk_path(path) return path def no_root(root, path): path = os.path.abspath(path) root = os.path.abspath(root) return path[len(root):] if path.startswith(root) else path def no_res_root(path): return os.path.relpath(path, get_config('storage')['resources']) def is_hidden(path): # TODO Add a lot of checks, recursive option (to check folders) # MacOSX has at least four ways to hide files... return os.path.basename(path).startswith(".") def wkt_to_proj4(wkt): srs = osr.SpatialReference() srs.ImportFromWkt(wkt) return srs.ExportToProj4() def proj4_to_wkt(proj4): srs = osr.SpatialReference() srs.ImportFromProj4(proj4) return srs.ExportToWkt() def wkt_to_authority(wkt): srs = osr.SpatialReference() srs.ImportFromWkt(wkt) # Are there really no other with osgeo? Oo if srs.GetAuthorityCode('PROJCS') != None: return srs.GetAuthorityName('PROJCS'), srs.GetAuthorityCode('PROJCS') elif srs.GetAuthorityCode('GEOGCS') != None : return srs.GetAuthorityName('GEOGCS'), srs.GetAuthorityCode('GEOGCS') else: return "Unknown", "Unknown"