Skip to content

Commit 80c91e6

Browse files
committed
Improving tile URI processing logic and other minor improvements
1 parent 72ac94d commit 80c91e6

3 files changed

Lines changed: 117 additions & 32 deletions

File tree

src/g_logger.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,31 +79,31 @@ void g_logger(int log_level, const char *format, ...)
7979
switch (log_level) {
8080
// Levels >= G_LOG_LEVEL_ERROR will terminate the program
8181
case G_LOG_LEVEL_ERROR:
82-
g_log_writer_standard_streams(log_level, log_fields, 1, NULL);
82+
g_log_writer_standard_streams((GLogLevelFlags)log_level, log_fields, 1, NULL);
8383
break;
8484

8585
// Levels <= G_LOG_LEVEL_INFO will only show when using G_MESSAGES_DEBUG
8686
case G_LOG_LEVEL_INFO:
87-
g_log_writer_standard_streams(log_level, log_fields, 1, NULL);
87+
g_log_writer_standard_streams((GLogLevelFlags)log_level, log_fields, 1, NULL);
8888
break;
8989

9090
default:
91-
g_log_writer_default(log_level, log_fields, 1, NULL);
91+
g_log_writer_default((GLogLevelFlags)log_level, log_fields, 1, NULL);
9292
}
9393
} else if (g_log_writer_is_journald(fileno(stderr))) {
9494
switch (log_level) {
9595
// Levels >= G_LOG_LEVEL_ERROR will terminate the program
9696
case G_LOG_LEVEL_ERROR:
97-
g_log_writer_journald(log_level, log_fields, 1, NULL);
97+
g_log_writer_journald((GLogLevelFlags)log_level, log_fields, 1, NULL);
9898
break;
9999

100100
// Levels <= G_LOG_LEVEL_INFO will only show when using G_MESSAGES_DEBUG
101101
case G_LOG_LEVEL_INFO:
102-
g_log_writer_journald(log_level, log_fields, 1, NULL);
102+
g_log_writer_journald((GLogLevelFlags)log_level, log_fields, 1, NULL);
103103
break;
104104

105105
default:
106-
g_log_writer_default(log_level, log_fields, 1, NULL);
106+
g_log_writer_default((GLogLevelFlags)log_level, log_fields, 1, NULL);
107107
}
108108
} else {
109109
setlogmask(LOG_UPTO(LOG_INFO));

src/gen_tile.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ struct projectionconfig *get_projection(const char *srs)
114114

115115
if (strstr(srs, "+proj=merc +a=6378137 +b=6378137") != NULL) {
116116
g_logger(G_LOG_LEVEL_DEBUG, "Using web mercator projection settings");
117-
prj = (struct projectionconfig *)malloc(sizeof(struct projectionconfig));
117+
prj = static_cast<struct projectionconfig *>(malloc(sizeof(struct projectionconfig)));
118118
prj->bound_x0 = -20037508.3428;
119119
prj->bound_x1 = 20037508.3428;
120120
prj->bound_y0 = -20037508.3428;
@@ -123,7 +123,7 @@ struct projectionconfig *get_projection(const char *srs)
123123
prj->aspect_y = 1;
124124
} else if (strcmp(srs, "+proj=eqc +lat_ts=0 +lat_0=0 +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs") == 0) {
125125
g_logger(G_LOG_LEVEL_DEBUG, "Using plate carree projection settings");
126-
prj = (struct projectionconfig *)malloc(sizeof(struct projectionconfig));
126+
prj = static_cast<struct projectionconfig *>(malloc(sizeof(struct projectionconfig)));
127127
prj->bound_x0 = -20037508.3428;
128128
prj->bound_x1 = 20037508.3428;
129129
prj->bound_y0 = -10018754.1714;
@@ -132,7 +132,7 @@ struct projectionconfig *get_projection(const char *srs)
132132
prj->aspect_y = 1;
133133
} else if (strcmp(srs, "+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +datum=OSGB36 +units=m +no_defs") == 0) {
134134
g_logger(G_LOG_LEVEL_DEBUG, "Using bng projection settings");
135-
prj = (struct projectionconfig *)malloc(sizeof(struct projectionconfig));
135+
prj = static_cast<struct projectionconfig *>(malloc(sizeof(struct projectionconfig)));
136136
prj->bound_x0 = 0;
137137
prj->bound_y0 = 0;
138138
prj->bound_x1 = 700000;
@@ -141,7 +141,7 @@ struct projectionconfig *get_projection(const char *srs)
141141
prj->aspect_y = 2;
142142
} else {
143143
g_logger(G_LOG_LEVEL_WARNING, "Unknown projection string, using web mercator as never the less. %s", srs);
144-
prj = (struct projectionconfig *)malloc(sizeof(struct projectionconfig));
144+
prj = static_cast<struct projectionconfig *>(malloc(sizeof(struct projectionconfig)));
145145
prj->bound_x0 = -20037508.3428;
146146
prj->bound_x1 = 20037508.3428;
147147
prj->bound_y0 = -20037508.3428;
@@ -187,7 +187,7 @@ static void load_fonts(const char *font_dir, int recurse)
187187
static void parameterize_map_max_connections(Map &m, int num_threads)
188188
{
189189
unsigned int i;
190-
char *tmp = (char *)malloc(20);
190+
char *tmp = static_cast<char *>(malloc(20));
191191

192192
for (i = 0; i < m.layer_count(); i++) {
193193
layer &l = m.get_layer(i);
@@ -283,7 +283,7 @@ static enum protoCmd render(struct xmlmapconfig *map, int x, int y, int z, char
283283

284284
for (yy = 0; yy < render_size_ty; yy++) {
285285
for (xx = 0; xx < render_size_tx; xx++) {
286-
mapnik::image_view<mapnik::image<mapnik::rgba8_t >> vw1(xx * map->tilesize, yy * map->tilesize, map->tilesize, map->tilesize, buf);
286+
mapnik::image_view<mapnik::image<mapnik::rgba8_t>> vw1(xx * map->tilesize, yy * map->tilesize, map->tilesize, map->tilesize, buf);
287287
struct mapnik::image_view_any vw(vw1);
288288
tiles.set(xx, yy, save_to_string(vw, map->output_format));
289289
}
@@ -292,7 +292,7 @@ static enum protoCmd render(struct xmlmapconfig *map, int x, int y, int z, char
292292
return cmdDone; // OK
293293
}
294294

295-
#else // METATILE
295+
#else // METATILE
296296
static enum protoCmd render(Map &m, const char *tile_dir, char *xmlname, projection &prj, int x, int y, int z, char *outputFormat)
297297
{
298298
char filename[PATH_MAX];

src/mod_tile.c

Lines changed: 104 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,6 @@ struct storage_backends {
9494
int noBackends;
9595
};
9696

97-
static int error_message(request_rec *r, const char *format, ...)
98-
__attribute__((format(printf, 2, 3)));
99-
10097
static int error_message(request_rec *r, const char *format, ...)
10198
{
10299
va_list ap;
@@ -1088,9 +1085,45 @@ static int tile_storage_hook(request_rec *r)
10881085
return HTTP_NOT_FOUND;
10891086
}
10901087

1088+
/**
1089+
* Safely converts a string to an integer.
1090+
* Returns APR_SUCCESS if the whole string was a valid number.
1091+
*/
1092+
static apr_status_t safe_parse_int(const char *str, int *result)
1093+
{
1094+
char *endptr;
1095+
1096+
if (!str || *str == '\0') {
1097+
return APR_EINVAL;
1098+
}
1099+
1100+
// We use base 10 for coordinates
1101+
apr_int64_t val = apr_strtoi64(str, &endptr, 10);
1102+
1103+
// Check if we reached the end of the string.
1104+
// If *endptr isn't '\0', it means there was non-numeric garbage.
1105+
if (*endptr != '\0') {
1106+
return APR_EINVAL;
1107+
}
1108+
1109+
*result = (int)val;
1110+
return APR_SUCCESS;
1111+
}
1112+
1113+
// helper to split the extension from the filename (e.g., "12.png" -> "png")
1114+
static void get_extension(char *filename, char *ext_dest, size_t dest_len)
1115+
{
1116+
char *dot = strrchr(filename, '.');
1117+
1118+
if (dot) {
1119+
apr_cpystrn(ext_dest, dot + 1, dest_len);
1120+
*dot = '\0'; // Truncate the filename at the dot to leave just the number
1121+
}
1122+
}
1123+
10911124
static int tile_translate(request_rec *r)
10921125
{
1093-
int i, n, limit, oob;
1126+
int basuri_len, i, limit, oob;
10941127
char option[11];
10951128
char extension[256];
10961129

@@ -1124,18 +1157,19 @@ static int tile_translate(request_rec *r)
11241157

11251158
for (i = 0; i < scfg->configs->nelts; ++i) {
11261159
tile_config_rec *tile_config = &tile_configs[i];
1160+
basuri_len = strlen(tile_config->baseuri);
11271161

11281162
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "tile_translate: testing baseuri(%s) name(%s) extension(%s)",
11291163
tile_config->baseuri, tile_config->xmlname, tile_config->fileExtension);
11301164

1131-
if (!strncmp(tile_config->baseuri, r->uri, strlen(tile_config->baseuri))) {
1165+
if (!strncmp(tile_config->baseuri, r->uri, basuri_len)) {
11321166

11331167
struct tile_request_data *rdata = (struct tile_request_data *)apr_pcalloc(r->pool, sizeof(struct tile_request_data));
11341168
struct protocol *cmd = (struct protocol *)apr_pcalloc(r->pool, sizeof(struct protocol));
11351169
bzero(cmd, sizeof(struct protocol));
11361170
bzero(rdata, sizeof(struct tile_request_data));
11371171

1138-
if (!strncmp(r->uri + strlen(tile_config->baseuri), "tile-layer.json", strlen("tile-layer.json"))) {
1172+
if (!strncmp(r->uri + basuri_len, "tile-layer.json", strlen("tile-layer.json"))) {
11391173
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "tile_translate: Requesting tileJSON for tilelayer %s", tile_config->xmlname);
11401174
r->handler = "tile_json";
11411175
rdata->layerNumber = i;
@@ -1145,24 +1179,75 @@ static int tile_translate(request_rec *r)
11451179

11461180
char parameters[XMLCONFIG_MAX];
11471181

1148-
if (tile_config->enableOptions) {
1182+
// 1. Get the part of the URI after the base
1183+
char *path_info = apr_pstrdup(r->pool, r->uri + basuri_len);
1184+
1185+
// 2. Tokenize into an array
1186+
// We split by "/" to get parts like ["layername", "12", "123", "456.png", "option"]
1187+
apr_array_header_t *parts = apr_array_make(r->pool, 6, sizeof(char *));
1188+
char *last;
1189+
char *token = apr_strtok(path_info, "/", &last);
1190+
1191+
while (token) {
1192+
*(char **)apr_array_push(parts) = token;
1193+
token = apr_strtok(NULL, "/", &last);
1194+
}
1195+
1196+
char **elts = (char **)parts->elts;
1197+
int n_parts = parts->nelts;
1198+
1199+
// 3. Path processing logic
1200+
if (tile_config->enableOptions && n_parts >= 4) {
1201+
// Expected: /parameter_options/z/x/y.ext/option
11491202
cmd->ver = PROTO_VER;
1150-
n = sscanf(r->uri + strlen(tile_config->baseuri), "%40[^/]/%d/%d/%d.%255[a-z]/%10s", parameters, &(cmd->z), &(cmd->x), &(cmd->y), extension, option);
1203+
apr_cpystrn(parameters, elts[0], 41);
11511204

1152-
if (n < 5) {
1153-
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "tile_translate: Invalid URL for tilelayer %s with options", tile_config->xmlname);
1205+
// Parse Z, X, Y safely
1206+
if (safe_parse_int(elts[1], &(cmd->z)) != APR_SUCCESS ||
1207+
safe_parse_int(elts[2], &(cmd->x)) != APR_SUCCESS) {
1208+
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "tile_translate: Invalid Z/X coordinates: %s/%s", elts[1], elts[2]);
11541209
return DECLINED;
11551210
}
1156-
} else {
1211+
1212+
// Special handling for elts[3] which is "y.ext"
1213+
char *y_str = apr_pstrdup(r->pool, elts[3]);
1214+
get_extension(y_str, extension, 256); // This null-terminates y_str at the dot
1215+
1216+
if (safe_parse_int(y_str, &(cmd->y)) != APR_SUCCESS) {
1217+
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "tile_translate: Invalid Y coordinate: %s", y_str);
1218+
return DECLINED;
1219+
}
1220+
1221+
if (n_parts >= 5) {
1222+
apr_cpystrn(option, elts[4], 11);
1223+
}
1224+
} else if (!tile_config->enableOptions && n_parts >= 3) {
1225+
// Expected: /z/x/y.ext/option
11571226
cmd->ver = 2;
1158-
n = sscanf(r->uri + strlen(tile_config->baseuri), "%d/%d/%d.%255[a-z]/%10s", &(cmd->z), &(cmd->x), &(cmd->y), extension, option);
1227+
parameters[0] = '\0';
11591228

1160-
if (n < 4) {
1161-
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "tile_translate: Invalid URL for tilelayer %s without options", tile_config->xmlname);
1229+
// Parse Z, X, Y safely
1230+
if (safe_parse_int(elts[0], &(cmd->z)) != APR_SUCCESS ||
1231+
safe_parse_int(elts[1], &(cmd->x)) != APR_SUCCESS) {
1232+
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "tile_translate: Invalid Z/X coordinates: %s/%s", elts[0], elts[1]);
11621233
return DECLINED;
11631234
}
11641235

1165-
parameters[0] = 0;
1236+
// Special handling for elts[2] which is "y.ext"
1237+
char *y_str = apr_pstrdup(r->pool, elts[2]);
1238+
get_extension(y_str, extension, 256); // This null-terminates y_str at the dot
1239+
1240+
if (safe_parse_int(y_str, &(cmd->y)) != APR_SUCCESS) {
1241+
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "tile_translate: Invalid Y coordinate: %s", y_str);
1242+
return DECLINED;
1243+
}
1244+
1245+
if (n_parts >= 4) {
1246+
apr_cpystrn(option, elts[3], 11);
1247+
}
1248+
} else {
1249+
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "tile_translate: Invalid tile path structure");
1250+
return DECLINED;
11661251
}
11671252

11681253
if (strcmp(extension, tile_config->fileExtension) != 0) {
@@ -1188,9 +1273,9 @@ static int tile_translate(request_rec *r)
11881273
return HTTP_NOT_FOUND;
11891274
}
11901275

1191-
strcpy(cmd->xmlname, tile_config->xmlname);
1192-
strcpy(cmd->mimetype, tile_config->mimeType);
1193-
strcpy(cmd->options, parameters);
1276+
apr_cpystrn(cmd->xmlname, tile_config->xmlname, XMLCONFIG_MAX);
1277+
apr_cpystrn(cmd->mimetype, tile_config->mimeType, XMLCONFIG_MAX);
1278+
apr_cpystrn(cmd->options, parameters, XMLCONFIG_MAX);
11941279

11951280
// Store a copy for later
11961281
rdata->cmd = cmd;
@@ -1211,7 +1296,7 @@ static int tile_translate(request_rec *r)
12111296

12121297
r->filename = NULL;
12131298

1214-
if ((tile_config->enableOptions && (n == 6)) || (!tile_config->enableOptions && (n == 5))) {
1299+
if ((tile_config->enableOptions && (n_parts == 5)) || (!tile_config->enableOptions && (n_parts == 4))) {
12151300
if (!strcmp(option, "status")) {
12161301
r->handler = "tile_status";
12171302
} else if (!strcmp(option, "dirty")) {

0 commit comments

Comments
 (0)