1 /******************************************************************************
2  * $Id$
3  *
4  * Project:  MapServer
5  * Purpose:  MapCache tile caching support file: Virtualearth quadkey service
6  * Author:   Thomas Bonfort and the MapServer team.
7  *
8  ******************************************************************************
9  * Copyright (c) 1996-2011 Regents of the University of Minnesota.
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a
12  * copy of this software and associated documentation files (the "Software"),
13  * to deal in the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  * and/or sell copies of the Software, and to permit persons to whom the
16  * Software is furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included in
19  * all copies of this Software or works derived from this Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  *****************************************************************************/
29 
30 #include "mapcache.h"
31 #include <apr_strings.h>
32 #include <math.h>
33 #include "mapcache_services.h"
34 
35 /** \addtogroup services */
36 
37 /** @{ */
38 
39 
_create_capabilities_ve(mapcache_context * ctx,mapcache_request_get_capabilities * req,char * url,char * path_info,mapcache_cfg * cfg)40 void _create_capabilities_ve(mapcache_context *ctx, mapcache_request_get_capabilities *req, char *url, char *path_info, mapcache_cfg *cfg)
41 {
42   ctx->set_error(ctx, 501, "ve service does not support capapbilities");
43 }
44 
45 /**
46  * \brief parse a VE request
47  * \private \memberof mapcache_service_ve
48  * \sa mapcache_service::parse_request()
49  */
_mapcache_service_ve_parse_request(mapcache_context * ctx,mapcache_service * this,mapcache_request ** request,const char * cpathinfo,apr_table_t * params,mapcache_cfg * config)50 void _mapcache_service_ve_parse_request(mapcache_context *ctx, mapcache_service *this, mapcache_request **request,
51     const char *cpathinfo, apr_table_t *params, mapcache_cfg *config)
52 {
53   int i,x,y,z;
54   const char *layer, *quadkey;
55   mapcache_tileset *tileset = NULL;
56   mapcache_grid_link *grid_link = NULL;
57   mapcache_tile *tile;
58   mapcache_request_get_tile *req;
59 
60   layer = apr_table_get(params, "layer");
61   if (layer) {
62     /*tileset not found directly, test if it was given as "name@grid" notation*/
63     char *tname = apr_pstrdup(ctx->pool, layer);
64     char *gname = tname;
65     while (*gname) {
66       if (*gname == '@') {
67         *gname = '\0';
68         gname++;
69         break;
70       }
71       gname++;
72     }
73     if (!gname) {
74       ctx->set_error(ctx, 404, "received ve request with invalid layer %s", layer);
75       return;
76     }
77     tileset = mapcache_configuration_get_tileset(config, tname);
78     if (!tileset) {
79       ctx->set_error(ctx, 404, "received ve request with invalid layer %s", tname);
80       return;
81     }
82     for (i = 0; i < tileset->grid_links->nelts; i++) {
83       mapcache_grid_link *sgrid = APR_ARRAY_IDX(tileset->grid_links, i, mapcache_grid_link*);
84       if (!strcmp(sgrid->grid->name, gname)) {
85         grid_link = sgrid;
86         break;
87       }
88     }
89     if (!grid_link) {
90       ctx->set_error(ctx, 404, "received ve request with invalid grid %s", gname);
91       return;
92     }
93   } else {
94     ctx->set_error(ctx, 400, "received ve request with no layer");
95     return;
96   }
97 
98   quadkey = apr_table_get(params, "tile");
99   tile = mapcache_tileset_tile_create(ctx->pool, tileset, grid_link);
100   if (quadkey) {
101     mapcache_util_quadkey_decode(ctx, quadkey, &x, &y, &z);
102     GC_CHECK_ERROR(ctx);
103     if (z < 1 || z >= grid_link->grid->nlevels) {
104       ctx->set_error(ctx, 404, "received ve request with invalid z level %d\n", z);
105       return;
106     }
107   } else {
108     ctx->set_error(ctx, 400, "received ve request with no tile quadkey");
109     return;
110   }
111 
112 
113   req = (mapcache_request_get_tile*) apr_pcalloc(ctx->pool, sizeof (mapcache_request_get_tile));
114   ((mapcache_request*)req)->type = MAPCACHE_REQUEST_GET_TILE;
115   req->ntiles = 1;
116   req->tiles = (mapcache_tile**) apr_pcalloc(ctx->pool, sizeof (mapcache_tile*));
117   req->tiles[0] = tile;
118   tile->z = z;
119   switch (grid_link->grid->origin) {
120     case MAPCACHE_GRID_ORIGIN_BOTTOM_LEFT:
121       req->tiles[0]->x = x;
122       req->tiles[0]->y = grid_link->grid->levels[z]->maxy - y - 1;
123       break;
124     case MAPCACHE_GRID_ORIGIN_TOP_LEFT:
125       req->tiles[0]->x = x;
126       req->tiles[0]->y = y;
127       break;
128     case MAPCACHE_GRID_ORIGIN_BOTTOM_RIGHT:
129       req->tiles[0]->x = grid_link->grid->levels[z]->maxx - x - 1;
130       req->tiles[0]->y = y;
131       break;
132     case MAPCACHE_GRID_ORIGIN_TOP_RIGHT:
133       req->tiles[0]->x = grid_link->grid->levels[z]->maxx - x - 1;
134       req->tiles[0]->y = grid_link->grid->levels[z]->maxy - y - 1;
135       break;
136   }
137   mapcache_tileset_tile_validate(ctx, req->tiles[0]);
138   GC_CHECK_ERROR(ctx);
139   *request = (mapcache_request*) req;
140   return;
141 }
142 
mapcache_service_ve_create(mapcache_context * ctx)143 mapcache_service* mapcache_service_ve_create(mapcache_context *ctx)
144 {
145   mapcache_service_ve* service = (mapcache_service_ve*) apr_pcalloc(ctx->pool, sizeof (mapcache_service_ve));
146   if (!service) {
147     ctx->set_error(ctx, 500, "failed to allocate ve service");
148     return NULL;
149   }
150   service->service.url_prefix = apr_pstrdup(ctx->pool, "ve");
151   service->service.name = apr_pstrdup(ctx->pool, "ve");
152   service->service.type = MAPCACHE_SERVICE_VE;
153   service->service.parse_request = _mapcache_service_ve_parse_request;
154   service->service.create_capabilities_response = _create_capabilities_ve;
155   return (mapcache_service*) service;
156 }
157 
158 /** @} */
159 /* vim: ts=2 sts=2 et sw=2
160 */
161