void parseTileset(mapcache_context *ctx, ezxml_t node, mapcache_cfg *config) { char *name = NULL; mapcache_tileset *tileset = NULL; ezxml_t cur_node; char* value; int havewgs84bbox=0; if(config->mode == MAPCACHE_MODE_NORMAL) { name = (char*)ezxml_attr(node,"name"); } else { name = "mirror"; } if(!name || !strlen(name)) { ctx->set_error(ctx, 400, "mandatory attribute \"name\" not found in <tileset>"); return; } else { name = apr_pstrdup(ctx->pool, name); /* check we don't already have a cache defined with this name */ if(mapcache_configuration_get_tileset(config, name)) { ctx->set_error(ctx, 400, "duplicate tileset with name \"%s\"",name); return; } } tileset = mapcache_tileset_create(ctx); tileset->name = name; if ((cur_node = ezxml_child(node,"read-only")) != NULL) { if(cur_node->txt && !strcmp(cur_node->txt,"true")) tileset->read_only = 1; } if ((cur_node = ezxml_child(node,"metadata")) != NULL) { parseMetadata(ctx, cur_node, tileset->metadata); GC_CHECK_ERROR(ctx); } if ((value = (char*)apr_table_get(tileset->metadata,"wgs84boundingbox")) != NULL) { double *values; int nvalues; value = apr_pstrdup(ctx->pool,value); if(MAPCACHE_SUCCESS != mapcache_util_extract_double_list(ctx, value, NULL, &values, &nvalues) || nvalues != 4) { ctx->set_error(ctx, 400, "failed to parse extent array %s." "(expecting 4 space separated numbers, got %d (%f %f %f %f)" "eg <wgs84bbox>-180 -90 180 90</wgs84bbox>", value,nvalues,values[0],values[1],values[2],values[3]); return; } tileset->wgs84bbox.minx = values[0]; tileset->wgs84bbox.miny = values[1]; tileset->wgs84bbox.maxx = values[2]; tileset->wgs84bbox.maxy = values[3]; havewgs84bbox = 1; } for(cur_node = ezxml_child(node,"grid"); cur_node; cur_node = cur_node->next) { mapcache_grid *grid; mapcache_grid_link *gridlink; char *restrictedExtent = NULL, *sTolerance = NULL; mapcache_extent *extent; int tolerance; if (tileset->grid_links == NULL) { tileset->grid_links = apr_array_make(ctx->pool,1,sizeof(mapcache_grid_link*)); } grid = mapcache_configuration_get_grid(config, cur_node->txt); if(!grid) { ctx->set_error(ctx, 400, "tileset \"%s\" references grid \"%s\"," " but it is not configured", name, cur_node->txt); return; } gridlink = apr_pcalloc(ctx->pool,sizeof(mapcache_grid_link)); gridlink->grid = grid; gridlink->minz = 0; gridlink->maxz = grid->nlevels; gridlink->grid_limits = (mapcache_extent_i*)apr_pcalloc(ctx->pool,grid->nlevels*sizeof(mapcache_extent_i)); gridlink->outofzoom_strategy = MAPCACHE_OUTOFZOOM_NOTCONFIGURED; gridlink->intermediate_grids = apr_array_make(ctx->pool,1,sizeof(mapcache_grid_link*)); restrictedExtent = (char*)ezxml_attr(cur_node,"restricted_extent"); if(restrictedExtent) { int nvalues; double *values; restrictedExtent = apr_pstrdup(ctx->pool,restrictedExtent); if(MAPCACHE_SUCCESS != mapcache_util_extract_double_list(ctx, restrictedExtent, NULL, &values, &nvalues) || nvalues != 4) { ctx->set_error(ctx, 400, "failed to parse extent array %s." "(expecting 4 space separated numbers, " "eg <grid restricted_extent=\"-180 -90 180 90\">foo</grid>", restrictedExtent); return; } gridlink->restricted_extent = (mapcache_extent*) apr_pcalloc(ctx->pool, sizeof(mapcache_extent)); gridlink->restricted_extent->minx = values[0]; gridlink->restricted_extent->miny = values[1]; gridlink->restricted_extent->maxx = values[2]; gridlink->restricted_extent->maxy = values[3]; extent = gridlink->restricted_extent; } else { extent = &grid->extent; } tolerance = 5; sTolerance = (char*)ezxml_attr(cur_node,"tolerance"); if(sTolerance) { char *endptr; tolerance = (int)strtol(sTolerance,&endptr,10); if(*endptr != 0 || tolerance < 0) { ctx->set_error(ctx, 400, "failed to parse grid tolerance %s (expecting a positive integer)", sTolerance); return; } } sTolerance = (char*)ezxml_attr(cur_node,"use_wms_intermediate_resolutions"); if(sTolerance && !strcmp(sTolerance,"true")) { mapcache_grid_link *intermediate_gridlink = apr_pcalloc(ctx->pool,sizeof(mapcache_grid_link)); APR_ARRAY_PUSH(gridlink->intermediate_grids,mapcache_grid_link*) = intermediate_gridlink; } mapcache_grid_compute_limits(grid,extent,gridlink->grid_limits,tolerance); sTolerance = (char*)ezxml_attr(cur_node,"minzoom"); if(sTolerance) { char *endptr; tolerance = (int)strtol(sTolerance,&endptr,10); if(*endptr != 0 || tolerance < 0) { ctx->set_error(ctx, 400, "failed to parse grid minzoom %s (expecting a positive integer)", sTolerance); return; } gridlink->minz = tolerance; } sTolerance = (char*)ezxml_attr(cur_node,"maxzoom"); if(sTolerance) { char *endptr; tolerance = (int)strtol(sTolerance,&endptr,10); if(*endptr != 0 || tolerance < 0) { ctx->set_error(ctx, 400, "failed to parse grid maxzoom %s (expecting a positive integer)", sTolerance); return; } gridlink->maxz = tolerance + 1; } if(gridlink->minz<0 || gridlink->maxz>grid->nlevels || gridlink->minz>=gridlink->maxz) { ctx->set_error(ctx, 400, "invalid grid maxzoom/minzoom %d/%d", gridlink->minz,gridlink->maxz); return; } sTolerance = (char*)ezxml_attr(cur_node,"max-cached-zoom"); /* RFC97 implementation: check for a maximum zoomlevel to cache */ if(sTolerance) { char *endptr; tolerance = (int)strtol(sTolerance,&endptr,10); if(*endptr != 0 || tolerance < 0) { ctx->set_error(ctx, 400, "failed to parse grid max-cached-zoom %s (expecting a positive integer)", sTolerance); return; } if(tolerance > gridlink->maxz) { ctx->set_error(ctx, 400, "failed to parse grid max-cached-zoom %s (max cached zoom is greater than grid's max zoom)", sTolerance); return; } gridlink->max_cached_zoom = tolerance; /* default to reassembling */ gridlink->outofzoom_strategy = MAPCACHE_OUTOFZOOM_REASSEMBLE; sTolerance = (char*)ezxml_attr(cur_node,"out-of-zoom-strategy"); if(sTolerance) { if(!strcasecmp(sTolerance,"reassemble")) { gridlink->outofzoom_strategy = MAPCACHE_OUTOFZOOM_REASSEMBLE; } else if(!strcasecmp(sTolerance,"proxy")) { gridlink->outofzoom_strategy = MAPCACHE_OUTOFZOOM_PROXY; } else { ctx->set_error(ctx, 400, "failed to parse grid out-of-zoom-strategy %s (expecting \"reassemble\" or \"proxy\")", sTolerance); return; } } } /* compute wgs84 bbox if it wasn't supplied already */ if(!havewgs84bbox && !strcasecmp(grid->srs,"EPSG:4326")) { tileset->wgs84bbox = *extent; } if(gridlink->intermediate_grids->nelts > 0) { double factor = 0.5, unitheight,unitwidth; int i; mapcache_grid_link *igl = APR_ARRAY_IDX(gridlink->intermediate_grids, 0, mapcache_grid_link*); igl->restricted_extent = gridlink->restricted_extent; igl->minz = gridlink->minz; igl->max_cached_zoom = gridlink->max_cached_zoom - 1; igl->maxz = gridlink->maxz - 1; igl->outofzoom_strategy = gridlink->outofzoom_strategy; igl->grid = mapcache_grid_create(ctx->pool); igl->grid->extent = gridlink->grid->extent; igl->grid->name = apr_psprintf(ctx->pool,"%s_intermediate_%g",gridlink->grid->name,factor); igl->grid->nlevels = gridlink->grid->nlevels - 1; igl->grid->origin = gridlink->grid->origin; igl->grid->srs = gridlink->grid->srs; igl->grid->srs_aliases = gridlink->grid->srs_aliases; igl->grid->unit = gridlink->grid->unit; igl->grid->tile_sx = gridlink->grid->tile_sx + gridlink->grid->tile_sx * factor; igl->grid->tile_sy = gridlink->grid->tile_sy + gridlink->grid->tile_sy * factor; igl->grid->levels = (mapcache_grid_level**)apr_pcalloc(ctx->pool, igl->grid->nlevels*sizeof(mapcache_grid_level*)); for(i=0; i<igl->grid->nlevels; i++) { mapcache_grid_level *level = (mapcache_grid_level*)apr_pcalloc(ctx->pool,sizeof(mapcache_grid_level)); level->resolution = gridlink->grid->levels[i]->resolution + (gridlink->grid->levels[i+1]->resolution - gridlink->grid->levels[i]->resolution) * factor; unitheight = igl->grid->tile_sy * level->resolution; unitwidth = igl->grid->tile_sx * level->resolution; level->maxy = ceil((igl->grid->extent.maxy-igl->grid->extent.miny - 0.01* unitheight)/unitheight); level->maxx = ceil((igl->grid->extent.maxx-igl->grid->extent.minx - 0.01* unitwidth)/unitwidth); igl->grid->levels[i] = level; } igl->grid_limits = (mapcache_extent_i*)apr_pcalloc(ctx->pool,igl->grid->nlevels*sizeof(mapcache_extent_i)); mapcache_grid_compute_limits(igl->grid,extent,igl->grid_limits,tolerance); }
void parseTileset(mapcache_context *ctx, ezxml_t node, mapcache_cfg *config) { char *name = NULL; mapcache_tileset *tileset = NULL; ezxml_t cur_node; char* value; int havewgs84bbox=0; if(config->mode == MAPCACHE_MODE_NORMAL) { name = (char*)ezxml_attr(node,"name"); } else { name = "mirror"; } if(!name || !strlen(name)) { ctx->set_error(ctx, 400, "mandatory attribute \"name\" not found in <tileset>"); return; } else { name = apr_pstrdup(ctx->pool, name); /* check we don't already have a cache defined with this name */ if(mapcache_configuration_get_tileset(config, name)) { ctx->set_error(ctx, 400, "duplicate tileset with name \"%s\"",name); return; } } tileset = mapcache_tileset_create(ctx); tileset->name = name; if ((cur_node = ezxml_child(node,"metadata")) != NULL) { parseMetadata(ctx, cur_node, tileset->metadata); GC_CHECK_ERROR(ctx); } if ((value = (char*)apr_table_get(tileset->metadata,"wgs84boundingbox")) != NULL) { double *values; int nvalues; value = apr_pstrdup(ctx->pool,value); if(MAPCACHE_SUCCESS != mapcache_util_extract_double_list(ctx, value, NULL, &values, &nvalues) || nvalues != 4) { ctx->set_error(ctx, 400, "failed to parse extent array %s." "(expecting 4 space separated numbers, got %d (%f %f %f %f)" "eg <wgs84bbox>-180 -90 180 90</wgs84bbox>", value,nvalues,values[0],values[1],values[2],values[3]); return; } tileset->wgs84bbox[0] = values[0]; tileset->wgs84bbox[1] = values[1]; tileset->wgs84bbox[2] = values[2]; tileset->wgs84bbox[3] = values[3]; havewgs84bbox = 1; } for(cur_node = ezxml_child(node,"grid"); cur_node; cur_node = cur_node->next) { int i; mapcache_grid *grid; mapcache_grid_link *gridlink; char *restrictedExtent = NULL, *sTolerance = NULL; double *extent; int tolerance; if (tileset->grid_links == NULL) { tileset->grid_links = apr_array_make(ctx->pool,1,sizeof(mapcache_grid_link*)); } grid = mapcache_configuration_get_grid(config, cur_node->txt); if(!grid) { ctx->set_error(ctx, 400, "tileset \"%s\" references grid \"%s\"," " but it is not configured", name, cur_node->txt); return; } gridlink = apr_pcalloc(ctx->pool,sizeof(mapcache_grid_link)); gridlink->grid = grid; gridlink->minz = 0; gridlink->maxz = grid->nlevels; gridlink->grid_limits = apr_pcalloc(ctx->pool,grid->nlevels*sizeof(int*)); for(i=0;i<grid->nlevels;i++) { gridlink->grid_limits[i] = apr_pcalloc(ctx->pool,4*sizeof(int)); } restrictedExtent = (char*)ezxml_attr(cur_node,"restricted_extent"); if(restrictedExtent) { int nvalues; restrictedExtent = apr_pstrdup(ctx->pool,restrictedExtent); if(MAPCACHE_SUCCESS != mapcache_util_extract_double_list(ctx, restrictedExtent, NULL, &gridlink->restricted_extent, &nvalues) || nvalues != 4) { ctx->set_error(ctx, 400, "failed to parse extent array %s." "(expecting 4 space separated numbers, " "eg <grid restricted_extent=\"-180 -90 180 90\">foo</grid>", restrictedExtent); return; } extent = gridlink->restricted_extent; } else { extent = grid->extent; } tolerance = 5; sTolerance = (char*)ezxml_attr(cur_node,"tolerance"); if(sTolerance) { char *endptr; tolerance = (int)strtol(sTolerance,&endptr,10); if(*endptr != 0 || tolerance < 0) { ctx->set_error(ctx, 400, "failed to parse grid tolerance %s (expecting a positive integer)", sTolerance); return; } } mapcache_grid_compute_limits(grid,extent,gridlink->grid_limits,tolerance); sTolerance = (char*)ezxml_attr(cur_node,"minzoom"); if(sTolerance) { char *endptr; tolerance = (int)strtol(sTolerance,&endptr,10); if(*endptr != 0 || tolerance < 0) { ctx->set_error(ctx, 400, "failed to parse grid minzoom %s (expecting a positive integer)", sTolerance); return; } gridlink->minz = tolerance; } sTolerance = (char*)ezxml_attr(cur_node,"maxzoom"); if(sTolerance) { char *endptr; tolerance = (int)strtol(sTolerance,&endptr,10); if(*endptr != 0 || tolerance < 0) { ctx->set_error(ctx, 400, "failed to parse grid maxzoom %s (expecting a positive integer)", sTolerance); return; } gridlink->maxz = tolerance + 1; } if(gridlink->minz<0 || gridlink->maxz>grid->nlevels || gridlink->minz>=gridlink->maxz) { ctx->set_error(ctx, 400, "invalid grid maxzoom/minzoom %d/%d", gridlink->minz,gridlink->maxz); return; } /* compute wgs84 bbox if it wasn't supplied already */ if(!havewgs84bbox && !strcasecmp(grid->srs,"EPSG:4326")) { tileset->wgs84bbox[0] = extent[0]; tileset->wgs84bbox[1] = extent[1]; tileset->wgs84bbox[2] = extent[2]; tileset->wgs84bbox[3] = extent[3]; } APR_ARRAY_PUSH(tileset->grid_links,mapcache_grid_link*) = gridlink; } if ((cur_node = ezxml_child(node,"dimensions")) != NULL) { parseDimensions(ctx, cur_node, tileset); GC_CHECK_ERROR(ctx); } if ((cur_node = ezxml_child(node,"cache")) != NULL) { mapcache_cache *cache = mapcache_configuration_get_cache(config, cur_node->txt); if(!cache) { ctx->set_error(ctx, 400, "tileset \"%s\" references cache \"%s\"," " but it is not configured", name, cur_node->txt); return; } tileset->cache = cache; } if ((cur_node = ezxml_child(node,"source")) != NULL) { mapcache_source *source = mapcache_configuration_get_source(config, cur_node->txt); if(!source) { ctx->set_error(ctx, 400, "tileset \"%s\" references source \"%s\"," " but it is not configured", name, cur_node->txt); return; } tileset->source = source; } if ((cur_node = ezxml_child(node,"metatile")) != NULL) { int *values, nvalues; value = apr_pstrdup(ctx->pool,cur_node->txt); if(MAPCACHE_SUCCESS != mapcache_util_extract_int_list(ctx, cur_node->txt, NULL, &values, &nvalues) || nvalues != 2) { ctx->set_error(ctx, 400, "failed to parse metatile dimension %s." "(expecting 2 space separated integers, " "eg <metatile>5 5</metatile>", cur_node->txt); return; } tileset->metasize_x = values[0]; tileset->metasize_y = values[1]; } if ((cur_node = ezxml_child(node,"watermark")) != NULL) { if(!*cur_node->txt) { ctx->set_error(ctx,400, "watermark config entry empty"); return; } mapcache_tileset_add_watermark(ctx,tileset,cur_node->txt); GC_CHECK_ERROR(ctx); } if ((cur_node = ezxml_child(node,"expires")) != NULL) { char *endptr; tileset->expires = (int)strtol(cur_node->txt,&endptr,10); if(*endptr != 0) { ctx->set_error(ctx, 400, "failed to parse expires %s." "(expecting an integer, " "eg <expires>3600</expires>", cur_node->txt); return; } } if ((cur_node = ezxml_child(node,"auto_expire")) != NULL) { char *endptr; tileset->auto_expire = (int)strtol(cur_node->txt,&endptr,10); if(*endptr != 0) { ctx->set_error(ctx, 400, "failed to parse auto_expire %s." "(expecting an integer, " "eg <auto_expire>3600</auto_expire>", cur_node->txt); return; } } if ((cur_node = ezxml_child(node,"metabuffer")) != NULL) { char *endptr; tileset->metabuffer = (int)strtol(cur_node->txt,&endptr,10); if(*endptr != 0) { ctx->set_error(ctx, 400, "failed to parse metabuffer %s." "(expecting an integer, " "eg <metabuffer>1</metabuffer>", cur_node->txt); return; } } if ((cur_node = ezxml_child(node,"format")) != NULL) { mapcache_image_format *format = mapcache_configuration_get_image_format(config,cur_node->txt); if(!format) { ctx->set_error(ctx, 400, "tileset \"%s\" references format \"%s\"," " but it is not configured",name,cur_node->txt); return; } tileset->format = format; } mapcache_tileset_configuration_check(ctx,tileset); GC_CHECK_ERROR(ctx); mapcache_configuration_add_tileset(config,tileset,name); return; }