Latest changes
[handlerosm.git] / handler_server_info.c
blob7723b38387208cabaa9fb15747cabdaad0b32468
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 /* Cherokee
5 * Authors:
6 * Alvaro Lopez Ortega <alvaro@alobbs.com>
8 * Copyright (C) 2001-2008 Alvaro Lopez Ortega
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of version 2 of the GNU General Public
12 * License as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA
25 #include "common-internal.h"
26 #include "handler_server_info.h"
28 #ifdef HAVE_SYS_UTSNAME_H
29 # include <sys/utsname.h>
30 #endif
32 #include "util.h"
33 #include "connection.h"
34 #include "connection-protected.h"
35 #include "server.h"
36 #include "server-protected.h"
37 #include "plugin_loader.h"
38 #include "connection_info.h"
40 #define CHANGES_TIME_DEFAULT 1
41 #define CHANGES_TIME_MAX 24
43 #define OSM_TAG "osm"
44 #define OSM_VERSION "0.5"
45 #define OSM_GENERATOR "Cherokee/MonetDB OSM Server"
46 #define OSM_ATTRIBUTES "version=\"" OSM_VERSION "\" generator=\"" OSM_GENERATOR "\""
48 #define NODE_TAG "node"
49 #define NODE_ATTRIBUTES "id=\"%s\" lat=\"%s\" lon=\"%s\" visible=\"%s\" user=\"%s\" timestamp=\"%s\""
51 #define TAG_TAG "tag"
52 #define TAG_ATTRIBUTES "k=\"%s\" v=\"%s\""
54 #define WAY_TAG "way"
55 #define WAY_ATTRIBUTES "id=\"%s\" visible=\"%s\" user=\"%s\" timestamp=\"%s\""
57 #define ND_TAG "nd"
58 #define ND_ATTRIBUTES "ref=\"%s\""
60 #define RELATION_TAG "relation"
61 #define RELATION_ATTRIBUTES "id=\"%s\" visible=\"%s\" user=\"%s\" timestamp=\"%s\""
63 #define MEMBER_TAG "member"
64 #define MEMBER_ATTRIBUTES "type=\"%s\" ref=\"%s\" role=\"%s\""
65 #define MEMBER_TYPE_NODE "node"
66 #define MEMBER_TYPE_RELATION "relation"
68 #define XMLHEADER "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"CRLF
69 #define XML(THISTAG,LEVEL) LEVEL "<" THISTAG ## _TAG " " THISTAG ## _ATTRIBUTES
70 #define XMLCONTINUE ">" CRLF
71 #define XMLCLOSESHORT "/>" CRLF
72 #define XMLCLOSE(THISTAG,LEVEL) LEVEL "</" THISTAG ## _TAG ">" CRLF
74 #define PREFERENCES_TAG "preferences"
75 #define PREFERENCES_ATTRIBUTES ""
76 #define PREFERENCE_TAG "preference"
77 #define PREFERENCE_ATTRIBUTES "k=\"%s\" v=\"%s\""
79 #define SQL_BBOX " AND WithIn(g, 'POLYGON((%f %f, %f %f, %f %f, %f %f, %f %f))') = TRUE"
81 #define SQL_NODE "SELECT id, X(g), Y(g), visible, usernames.username, timestamp, k, v FROM nodes, usernames, node_tags WHERE id = node AND nodes.username = usernames.id"
82 #define SQL_NODE_BY_ID SQL_NODE " AND id = %ld"
83 #define SQL_NODE_BY_BBOX SQL_NODE " AND WithIn(g, 'POLYGON((%f %f, %f %f, %f %f, %f %f, %f %f))') = TRUE"
85 #define SQL_RELATION "SELECT DISTINCT id, visible, usernames.username, timestamp, k, v FROM relations, relation_tags, usernames WHERE relations.id = relation_tags.relation AND relations.username = usernames.id"
86 #define SQL_RELATION_BY_NODE "SELECT DISTINCT id, visible, usernames.username, timestamp, k, v FROM relations, usernames, relation_tags, nodes, members_node WHERE relations.username = usernames.id AND relation_tags.relation = id AND nodes.id = members_node.to_node AND members_node.relation = id"
87 #define SQL_RELATION_BY_NODE_ID SQL_RELATION_BY_NODE " AND nodes.id = %ld ORDER BY id"
88 #define SQL_RELATION_BY_BBOX SQL_RELATION_BY_NODE SQL_BBOX " ORDER BY id"
91 #define SQL_RELATION_BY_ID SQL_RELATION " AND id = %ld"
92 #define SQL_RELATION_MEMBER_NODE "SELECT DISTINCT relation, to_node, role FROM members_node, relation_tags WHERE relation_tags.relation = members_node.relation"
93 #define SQL_RELATION_MEMBER_NODE_BY_ID SQL_RELATION_MEMBER_NODE " AND relation=%ld"
94 #define SQL_RELATION_MEMBER_RELATION "SELECT DISTINCT relation, to_relation, role FROM members_relation, relation_tags WHERE relation_tags.relation = members_relation.relation"
95 #define SQL_RELATION_MEMBER_RELATION_BY_ID SQL_RELATION_MEMBER_RELATION " AND relation=%ld"
98 #define SQL_RELATION_MEMBER_NODE_BY_BBOX "SELECT DISTINCT relation, to_node, role FROM members_node, relation_tags, nodes WHERE relation_tags.relation = members_node.relation AND nodes.id = members_node.to_node " SQL_BBOX " ORDER BY relation, to_node"
99 #define SQL_RELATION_MEMBER_RELATION_BY_BBOX "SELECT DISTINCT relation, to_node, role FROM members_relation, relation_tags, nodes WHERE relation_tags.relation = members_relation.relation AND nodes.id = members_node.to_node" SQL_BBOX " ORDER BY relation, to_node"
102 #define SQL_WAY "SELECT DISTINCT id, visible, usernames.username, timestamp, k, v FROM relations, usernames, relation_tags, relation_tags AS constr WHERE relations.username = usernames.id AND relation_tags.relation = id AND constr.relation = relations.id AND constr.k='type' AND constr.v='way' AND k<>'type' AND v<>'way'"
103 #define SQL_WAY_BY_ID SQL_WAY " AND id=%ld"
104 #define SQL_WAY_ND "SELECT relation, to_node FROM members_node, relation_tags WHERE relation_tags.relation = members_node.relation AND k='type' AND v='way'"
105 #define SQL_WAY_ND_BY_ID SQL_WAY_ND " AND relation=%ld ORDER BY relation, to_node"
107 #define SQL_WAY_BY_NODE "SELECT DISTINCT id, visible, usernames.username, timestamp, k, v FROM relations, usernames, relation_tags, nodes, members_node, relation_tags AS constr WHERE relations.username = usernames.id AND relation_tags.relation = id AND constr.relation = id AND constr.k='type' AND constr.v='way' AND k<>'type' AND v<>'way' AND nodes.id = members_node.to_node AND members_node.relation = id"
108 #define SQL_WAY_BY_NODE_ID SQL_WAY_BY_NODE " AND nodes.id = %ld ORDER BY id"
110 #define SQL_WAY_BY_BBOX SQL_WAY_BY_NODE SQL_BBOX " ORDER BY id"
111 #define SQL_ND_BY_BBOX "SELECT DISTINCT relation, to_node FROM members_node, relation_tags, nodes WHERE relation_tags.relation = members_node.relation AND k='type' AND v='way' AND nodes.id = members_node.to_node" SQL_BBOX " ORDER BY relation, to_node"
113 //#define SQL_WAY_BY_BBOX "SELECT id, visible, usernames.username, timestamp, '', '', k, v FROM relations, usernames, relation_tags, relation_tags AS constr, nodes WHERE relations.username = usernames.id AND relation_tags.relation = id AND constr.relation = id AND constr.k='type' AND constr.v='way' AND k<>'type' AND v<>'way' AND nodes.id = constr."
115 //#define BBOX_SQL "SELECT id, X(g), Y(g), visible, timestamp, name, value FROM nodes, node_tags WHERE Touches(g, 'POLYGON((%f %f, %f %f, %f %f, %f %f, %f %f))') = TRUE AND nodes.id = node_tags.node"
119 //#define WAY_NODE "SELECT id, 'true', 'not_implemented', '2007-09-07T16:39:10+01:00', name, value FROM nodes LEFT JOIN node_tags ON id = node"
121 /* Plug-in initialization
123 PLUGIN_INFO_HANDLER_EASIEST_INIT (server_info, http_get | http_put | http_post );
126 /* Methods implementation
128 static ret_t
129 props_free (cherokee_handler_server_info_props_t *props)
131 return cherokee_module_props_free_base (MODULE_PROPS(props));
135 ret_t
136 cherokee_handler_server_info_configure (cherokee_config_node_t *conf, cherokee_server_t *srv, cherokee_module_props_t **_props)
138 cherokee_list_t *i;
139 cherokee_handler_server_info_props_t *props;
141 UNUSED(srv);
143 if (*_props == NULL) {
144 CHEROKEE_NEW_STRUCT (n, handler_server_info_props);
146 cherokee_module_props_init_base (MODULE_PROPS(n),
147 MODULE_PROPS_FREE(props_free));
148 n->just_about = false;
149 n->connection_details = false;
151 *_props = MODULE_PROPS(n);
154 props = PROP_SRV_INFO(*_props);
156 cherokee_config_node_foreach (i, conf) {
157 cherokee_config_node_t *subconf = CONFIG_NODE(i);
159 if (equal_buf_str (&subconf->key, "just_about")) {
160 props->just_about = atoi(subconf->val.buf);
161 } else if (equal_buf_str (&subconf->key, "connection_details")) {
162 props->connection_details = atoi(subconf->val.buf);
163 } else {
164 PRINT_MSG ("ERROR: Handler file: Unknown key: '%s'\n", subconf->key.buf);
165 return ret_error;
169 return ret_ok;
172 static void
173 user_preferences(cherokee_buffer_t *buf)
175 cherokee_buffer_t content = CHEROKEE_BUF_INIT;
176 cherokee_buffer_add_str (buf, XML(PREFERENCES, " "));
177 if (content.len > 0) {
178 cherokee_buffer_add_str (buf, XMLCONTINUE);
179 cherokee_buffer_add_buffer (buf, &content);
180 cherokee_buffer_mrproper (&content);
181 cherokee_buffer_add_str (buf, XMLCLOSE(PREFERENCES, " "));
182 } else
183 cherokee_buffer_add_str (buf, XMLCLOSESHORT);
185 printf("%s\n", __func__);
188 static void
189 gpx_data(cherokee_buffer_t *buf, unsigned long int id)
191 printf("%s\n", __func__);
194 static void
195 gpx_details(cherokee_buffer_t *buf, unsigned long int id)
197 printf("%s\n", __func__);
200 static void
201 node_ways(cherokee_buffer_t *buf, unsigned long int id)
203 printf("%s\n", __func__);
206 enum OSM_State { OSM_FIND_FIRST = 0, OSM_GPX_ID, OSM_GPX_COMMAND, OSM_NODE_ID, OSM_NODE_COMMAND, OSM_NODES, OSM_NODES_PRE_PARSE, OSM_WAY_ID, OSM_WAY_COMMAND, OSM_WAYS_PRE_PARSE, OSM_WAYS_SEARCH, OSM_RELATION_ID, OSM_RELATION_COMMAND, OSM_RELATIONS_PRE_PARSE, OSM_RELATIONS_SEARCH, OSM_DONE}; // Move to .h later
208 static void
209 objtype_full(cherokee_buffer_t *buf, unsigned long int id, enum OSM_State state)
211 printf("%s\n", __func__);
214 static void
215 objtype_history(cherokee_buffer_t *buf, unsigned long int id, enum OSM_State state)
217 printf("%s\n", __func__);
220 static void
221 objtype_relations(cherokee_buffer_t *buf, unsigned long int id, enum OSM_State state)
223 printf("%s\n", __func__);
226 parse_changes(cherokee_avl_t *arguments, cherokee_buffer_t *buf) {
227 unsigned long int hours;
228 unsigned long int zoom;
229 void *param;
230 ret_t ret;
232 ret = cherokee_avl_get_ptr (arguments, "zoom", &param);
233 if (ret == ret_ok) {
234 zoom = strtoul(param, (char **) NULL, 10);
235 } else
236 zoom = 12;
238 ret = cherokee_avl_get_ptr (arguments, "start", &param);
239 if (ret == ret_ok) {
240 void *param2;
241 ret = cherokee_avl_get_ptr (arguments, "end", &param2);
242 if (ret == ret_ok) {
243 changes_bystartend(buf, zoom, (char *)param, (char *)param2);
245 } else {
246 ret = cherokee_avl_get_ptr (arguments, "hours", &param);
247 if (ret == ret_ok) {
248 hours = strtoul(param, (char **) NULL, 10);
249 } else
250 hours = 1;
252 changes_byhour(buf, zoom, hours);
256 changes_byhour(cherokee_buffer_t *buf, unsigned long int zoom, unsigned long int hours) {
257 cherokee_buffer_add_va (buf, "%d %d", zoom, hours);
260 changes_bystartend(cherokee_buffer_t *buf, unsigned long int zoom, char *start, char *end) {
261 cherokee_buffer_add_va (buf, "%d %s %s", zoom, start, end);
264 static ret_t fetch_bbox(cherokee_avl_t *arguments, double *left, double *bottom, double *right, double *top) {
265 void *param;
266 if (ret_ok == cherokee_avl_get_ptr (arguments, "bbox", &param)) {
267 char *token;
268 char *string = (char *) param;
269 if ((token = (char *) strsep( &string , ",")) != NULL) {
270 *left = strtod(token, (char **) NULL);
271 if (errno != ERANGE && (token = (char *) strsep( &string , ",")) != NULL) {
272 *bottom = strtod(token, (char **) NULL);
273 if (errno != ERANGE && (token = (char *) strsep( &string , ",")) != NULL) {
274 *right = strtod(token, (char **) NULL);
275 if (errno != ERANGE && (token = (char *) strsep( &string , ",")) != NULL) {
276 *top = strtod(token, (char **) NULL);
277 if (errno != ERANGE) {
278 return ret_ok;
285 return ret_error;
288 static void parse_nodes(cherokee_avl_t *arguments, cherokee_buffer_t *buf) {
290 static void parse_nodes_search(cherokee_avl_t *arguments, cherokee_buffer_t *buf) {
293 static void parse_relations(cherokee_avl_t *arguments, cherokee_buffer_t *buf) {
295 static void parse_relations_search(cherokee_avl_t *arguments, cherokee_buffer_t *buf) {
298 static void parse_ways(cherokee_avl_t *arguments, cherokee_buffer_t *buf) {
300 static void parse_ways_search(cherokee_avl_t *arguments, cherokee_buffer_t *buf) {
302 static void parse_trackpoints(cherokee_avl_t *arguments, cherokee_buffer_t *buf) {
303 double left, bottom, right, top;
304 unsigned long int page;
305 void *param;
306 printf("%s\n", __func__);
308 if (ret_ok == fetch_bbox(arguments, &left, &bottom, &right, &top)) {
309 cherokee_buffer_add_va (buf, "%f %f %f %f", left, bottom, right, top);
312 if (ret_ok == cherokee_avl_get_ptr (arguments, "page", &param)) {
313 page = strtoul(param, (char **) NULL, 10);
314 if (errno == ERANGE)
315 page = 1;
316 } else {
317 page = 1;
321 static void result_node_to_xml(MapiHdl *hdl, cherokee_buffer_t *buf) {
322 unsigned long int id = 0, id_old = 0;
323 unsigned short int state = 3;
324 while (mapi_fetch_row(*hdl)) {
325 char *key, *value;
326 id = strtoul(mapi_fetch_field(*hdl, 0), (char **) NULL, 10);
327 if (id_old != id) {
328 switch (state) {
329 case 0:
330 cherokee_buffer_add_str (buf, XMLCLOSESHORT);
331 break;
332 case 1:
333 cherokee_buffer_add_va (buf, "%s", XMLCLOSE(NODE, " "));
334 break;
336 cherokee_buffer_add_va (buf, XML(NODE, " "), mapi_fetch_field(*hdl, 0),
337 mapi_fetch_field(*hdl, 1),
338 mapi_fetch_field(*hdl, 2),
339 mapi_fetch_field(*hdl, 3),
340 mapi_fetch_field(*hdl, 4),
341 mapi_fetch_field(*hdl, 5) );
343 state = 0;
344 id_old = id;
346 key = mapi_fetch_field(*hdl, 6);
347 value = mapi_fetch_field(*hdl, 7);
349 if (key != NULL && value != NULL) {
350 if (state == 0)
351 cherokee_buffer_add_str (buf, XMLCONTINUE);
353 state = 1;
354 cherokee_buffer_add_va (buf, XML(TAG, " ") XMLCLOSESHORT, mapi_fetch_field(*hdl, 6), mapi_fetch_field(*hdl, 7) );
357 switch (state) {
358 case 0:
359 cherokee_buffer_add_str (buf, XMLCLOSESHORT);
360 break;
361 case 1:
362 cherokee_buffer_add_va (buf, "%s", XMLCLOSE(NODE, " "));
363 break;
367 static void result_way_to_xml(MapiHdl *hdl, MapiHdl *hdl2, cherokee_buffer_t *buf) {
368 unsigned long int id = 0, id_old = 0;
369 unsigned short int state = 3;
370 while (mapi_fetch_row(*hdl)) {
371 char *key, *value;
372 id = strtoul(mapi_fetch_field(*hdl, 0), (char **) NULL, 10);
373 if (id_old != id) {
374 switch (state) {
375 case 0:
376 cherokee_buffer_add_str (buf, XMLCLOSESHORT);
377 break;
378 case 1:
379 cherokee_buffer_add_va (buf, "%s", XMLCLOSE(WAY, " "));
380 break;
382 cherokee_buffer_add_va (buf, XML(WAY, " "), mapi_fetch_field(*hdl, 0),
383 mapi_fetch_field(*hdl, 1),
384 mapi_fetch_field(*hdl, 2),
385 mapi_fetch_field(*hdl, 3) );
386 state = 0;
387 id_old = id;
389 if (mapi_get_row_count(*hdl2) > 0) {
390 while (mapi_fetch_row(*hdl2)) {
391 unsigned long int relationid = strtoul(mapi_fetch_field(*hdl2, 0), (char **) NULL, 10);
392 if (relationid == id) {
393 if (state == 0)
394 cherokee_buffer_add_str (buf, XMLCONTINUE);
395 state = 1;
396 cherokee_buffer_add_va (buf, XML(ND, " ")XMLCLOSESHORT, mapi_fetch_field(*hdl2, 1));
397 } else {
398 mapi_seek_row(*hdl2, -1, MAPI_SEEK_CUR);
399 break;
407 key = mapi_fetch_field(*hdl, 4);
408 value = mapi_fetch_field(*hdl, 5);
410 if (key != NULL && value != NULL) {
411 if (state == 0)
412 cherokee_buffer_add_str (buf, XMLCONTINUE);
414 state = 1;
415 cherokee_buffer_add_va (buf, XML(TAG, " ") XMLCLOSESHORT, key, value );
418 switch (state) {
419 case 0:
420 cherokee_buffer_add_str (buf, XMLCLOSESHORT);
421 break;
422 case 1:
423 cherokee_buffer_add_va (buf, "%s", XMLCLOSE(WAY, " "));
424 break;
428 static void result_relation_to_xml(MapiHdl *hdl, MapiHdl *hdl2, MapiHdl *hdl3, cherokee_buffer_t *buf) {
429 unsigned long int id = 0, id_old = 0;
430 unsigned short int state = 3;
431 while (mapi_fetch_row(*hdl)) {
432 char *key, *value;
433 id = strtoul(mapi_fetch_field(*hdl, 0), (char **) NULL, 10);
434 if (id_old != id) {
435 switch (state) {
436 case 0:
437 cherokee_buffer_add_str (buf, XMLCLOSESHORT);
438 break;
439 case 1:
440 cherokee_buffer_add_va (buf, "%s", XMLCLOSE(RELATION, " "));
441 break;
443 cherokee_buffer_add_va (buf, XML(RELATION, " "), mapi_fetch_field(*hdl, 0),
444 mapi_fetch_field(*hdl, 1),
445 mapi_fetch_field(*hdl, 2),
446 mapi_fetch_field(*hdl, 3) );
447 state = 0;
448 id_old = id;
450 if (mapi_get_row_count(*hdl2) > 0) {
451 while (mapi_fetch_row(*hdl2)) {
452 unsigned long int relationid = strtoul(mapi_fetch_field(*hdl2, 0), (char **) NULL, 10);
453 if (relationid == id) {
454 if (state == 0)
455 cherokee_buffer_add_str (buf, XMLCONTINUE);
456 state = 1;
457 cherokee_buffer_add_va (buf, XML(MEMBER, " ")XMLCLOSESHORT, MEMBER_TYPE_NODE, mapi_fetch_field(*hdl2, 1), mapi_fetch_field(*hdl2, 2));
458 } else {
459 mapi_seek_row(*hdl2, -1, MAPI_SEEK_CUR);
460 break;
464 if (mapi_get_row_count(*hdl3) > 0) {
465 while (mapi_fetch_row(*hdl3)) {
466 unsigned long int relationid = strtoul(mapi_fetch_field(*hdl3, 0), (char **) NULL, 10);
467 if (relationid == id) {
468 if (state == 0)
469 cherokee_buffer_add_str (buf, XMLCONTINUE);
470 state = 1;
471 cherokee_buffer_add_va (buf, XML(MEMBER, " ")XMLCLOSESHORT, MEMBER_TYPE_RELATION, mapi_fetch_field(*hdl3, 1), mapi_fetch_field(*hdl3, 2));
472 } else {
473 mapi_seek_row(*hdl3, -1, MAPI_SEEK_CUR);
474 break;
479 key = mapi_fetch_field(*hdl, 4);
480 value = mapi_fetch_field(*hdl, 5);
482 if (key != NULL && value != NULL) {
483 if (state == 0)
484 cherokee_buffer_add_str (buf, XMLCONTINUE);
486 state = 1;
487 cherokee_buffer_add_va (buf, XML(TAG, " ") XMLCLOSESHORT, key, value );
490 switch (state) {
491 case 0:
492 cherokee_buffer_add_str (buf, XMLCLOSESHORT);
493 break;
494 case 1:
495 cherokee_buffer_add_va (buf, "%s", XMLCLOSE(RELATION, " "));
496 break;
500 static void run_sql(cherokee_handler_server_info_t *hdl, cherokee_buffer_t *sql, cherokee_buffer_t *buf, void (*callback)()) {
501 MapiHdl mapi_hdl = NULL;
502 if ((mapi_hdl = mapi_query(hdl->dbh, sql->buf)) != NULL) {
503 callback(&mapi_hdl, buf);
504 mapi_cache_freeup(mapi_hdl, 100);
505 mapi_close_handle(mapi_hdl);
510 static void run_sql2(cherokee_handler_server_info_t *hdl, cherokee_buffer_t *sql, cherokee_buffer_t *sql2, cherokee_buffer_t *buf, void (*callback)()) {
511 MapiHdl mapi_hdl = NULL;
512 MapiHdl mapi_hdl2 = NULL;
514 if ((mapi_hdl = mapi_query(hdl->dbh, sql->buf)) != NULL) {
515 if ((mapi_hdl2 = mapi_query(hdl->dbh, sql2->buf)) != NULL) {
516 callback(&mapi_hdl, &mapi_hdl2, buf);
517 mapi_cache_freeup(mapi_hdl2, 100);
518 mapi_close_handle(mapi_hdl2);
520 mapi_cache_freeup(mapi_hdl, 100);
521 mapi_close_handle(mapi_hdl);
525 static void run_sql3(cherokee_handler_server_info_t *hdl, cherokee_buffer_t *sql, cherokee_buffer_t *sql2, cherokee_buffer_t *sql3, cherokee_buffer_t *buf, void (*callback)()) {
526 MapiHdl mapi_hdl = NULL;
527 MapiHdl mapi_hdl2 = NULL;
528 MapiHdl mapi_hdl3 = NULL;
530 if ((mapi_hdl = mapi_query(hdl->dbh, sql->buf)) != NULL) {
531 if ((mapi_hdl2 = mapi_query(hdl->dbh, sql2->buf)) != NULL) {
532 if ((mapi_hdl3 = mapi_query(hdl->dbh, sql3->buf)) != NULL) {
533 callback(&mapi_hdl, &mapi_hdl2, &mapi_hdl3, buf);
534 mapi_cache_freeup(mapi_hdl3, 100);
535 mapi_close_handle(mapi_hdl3);
537 mapi_cache_freeup(mapi_hdl2, 100);
538 mapi_close_handle(mapi_hdl2);
540 mapi_cache_freeup(mapi_hdl, 100);
541 mapi_close_handle(mapi_hdl);
546 static void get_object_by_id(cherokee_handler_server_info_t *hdl, unsigned long int id, cherokee_buffer_t *buf, enum OSM_State state) {
547 cherokee_buffer_t sql = CHEROKEE_BUF_INIT;
548 switch (state) {
549 case OSM_NODE_COMMAND:
550 cherokee_buffer_add_va (&sql, SQL_NODE_BY_ID, id);
551 run_sql(hdl, &sql, buf, result_node_to_xml);
552 break;
553 case OSM_WAY_COMMAND:
555 cherokee_buffer_t sql2 = CHEROKEE_BUF_INIT;
556 cherokee_buffer_add_va (&sql, SQL_WAY_BY_ID, id);
557 cherokee_buffer_add_va (&sql2, SQL_WAY_ND_BY_ID, id);
558 run_sql2(hdl, &sql, &sql2, buf, result_way_to_xml);
559 cherokee_buffer_mrproper(&sql2);
561 break;
562 case OSM_RELATION_COMMAND:
564 cherokee_buffer_t sql2 = CHEROKEE_BUF_INIT;
565 cherokee_buffer_t sql3 = CHEROKEE_BUF_INIT;
566 cherokee_buffer_add_va (&sql, SQL_RELATION_BY_ID, id);
567 cherokee_buffer_add_va (&sql2, SQL_RELATION_MEMBER_NODE_BY_ID, id);
568 cherokee_buffer_add_va (&sql3, SQL_RELATION_MEMBER_RELATION_BY_ID, id);
569 // printf("%s\n%s\n%s\n", sql.buf, sql2.buf, sql3.buf);
570 run_sql3(hdl, &sql, &sql2, &sql3, buf, result_relation_to_xml);
571 cherokee_buffer_mrproper(&sql2);
572 cherokee_buffer_mrproper(&sql3);
574 break;
575 default:
576 return;
578 cherokee_buffer_mrproper(&sql);
581 static void parse_map(cherokee_handler_server_info_t *hdl, cherokee_buffer_t *buf) {
582 double left, bottom, right, top;
583 cherokee_avl_t *arguments = HANDLER_CONN(hdl)->arguments;
585 if (ret_ok == fetch_bbox(arguments, &left, &bottom, &right, &top)) {
586 TRACE (ENTRIES, "%s BBOX: %f %f %f %f\n", __func__, left, bottom, right, top);
587 cherokee_buffer_t sql = CHEROKEE_BUF_INIT;
588 cherokee_buffer_t sql2 = CHEROKEE_BUF_INIT;
589 cherokee_buffer_t sql3 = CHEROKEE_BUF_INIT;
590 cherokee_buffer_add_va (&sql, SQL_NODE_BY_BBOX, bottom, left, bottom, right, top, right, top, left, bottom, left);
591 run_sql(hdl, &sql, buf, result_node_to_xml);
592 cherokee_buffer_mrproper(&sql);
593 cherokee_buffer_add_va (&sql, SQL_WAY_BY_BBOX, bottom, left, bottom, right, top, right, top, left, bottom, left);
594 cherokee_buffer_add_va (&sql2, SQL_ND_BY_BBOX, bottom, left, bottom, right, top, right, top, left, bottom, left);
595 run_sql2(hdl, &sql, &sql2, buf, result_way_to_xml);
596 cherokee_buffer_mrproper(&sql2);
597 cherokee_buffer_mrproper(&sql);
598 cherokee_buffer_add_va (&sql, SQL_RELATION_BY_BBOX, bottom, left, bottom, right, top, right, top, left, bottom, left);
599 cherokee_buffer_add_va (&sql2, SQL_RELATION_MEMBER_NODE_BY_BBOX, bottom, left, bottom, right, top, right, top, left, bottom, left);
600 cherokee_buffer_add_va (&sql3, SQL_RELATION_MEMBER_RELATION_BY_BBOX, bottom, left, bottom, right, top, right, top, left, bottom, left);
602 // printf("%s\n%s\n%s\n", sql.buf, sql2.buf, sql3.buf);
603 run_sql3(hdl, &sql, &sql2, &sql3, buf, result_relation_to_xml);
604 cherokee_buffer_mrproper(&sql3);
605 cherokee_buffer_mrproper(&sql2);
606 cherokee_buffer_mrproper(&sql);
611 static void
612 server_info_build_page (cherokee_handler_server_info_t *hdl)
614 ret_t ret;
615 cherokee_server_t *srv;
616 cherokee_connection_t *conn;
617 cherokee_buffer_t *buf;
618 cherokee_buffer_t content = CHEROKEE_BUF_INIT;
620 /* Init
622 buf = &hdl->buffer;
623 srv = HANDLER_SRV(hdl);
624 conn = HANDLER_CONN(hdl);
626 /* Parse the Request */
628 if (strlen(conn->request.buf) > 1) {
629 enum OSM_State state = OSM_FIND_FIRST;
630 unsigned long int id = 0;
631 char *string = conn->request.buf;
632 char *token;
633 void *param;
634 while (state != OSM_DONE && (token = (char *) strsep( &string , "/")) != NULL) {
635 if (*token == '\0')
636 continue;
638 switch (state) {
639 case OSM_FIND_FIRST:
640 switch (token[0]) {
641 case 'c':
642 /* GET /api/0.5/changes?hours=1&zoom=16&start=none&end=none */
643 parse_changes(conn->arguments, &content);
644 state = OSM_DONE;
645 break;
646 case 'n':
647 if (strlen(token) == 5 && token[4] == 's')
648 state = OSM_NODES_PRE_PARSE;
649 else
650 state = OSM_NODE_ID;
651 break;
652 case 'w':
653 if (strlen(token) == 4 && token[3] == 's')
654 state = OSM_WAYS_PRE_PARSE;
655 else
656 state = OSM_WAY_ID;
657 break;
658 case 'r':
659 if (strlen(token) == 9 && token[8] == 's')
660 state = OSM_RELATIONS_PRE_PARSE;
661 else
662 state = OSM_RELATION_ID;
663 break;
664 case 'g':
665 state = OSM_GPX_ID;
666 break;
667 case 'u':
668 user_preferences(&content);
669 break;
670 case 'm':
671 /* GET /api/0.5/map?bbox=LEFT,BOTTOM,RIGHT,TOP */
672 parse_map(hdl, &content);
673 break;
674 case 't':
675 /* GET /api/0.5/trackpoints?bbox=LEFT,BOTTOM,RIGHT,TOP&page=PAGENUMBER */
676 parse_trackpoints(conn->arguments, &content);
677 break;
678 case 's':
679 break;
681 break;
682 case OSM_GPX_ID:
683 case OSM_NODE_ID:
684 case OSM_WAY_ID:
685 case OSM_RELATION_ID:
686 id = strtoul(token, (char **) NULL, 10);
687 if (errno != ERANGE) {
688 state++;
689 get_object_by_id(hdl, id, &content, state);
690 } else
691 state = OSM_DONE;
692 break;
693 case OSM_GPX_COMMAND:
694 if (strlen(token) > 1) {
695 switch (token[1]) {
696 case 'a':
697 /* GET /api/0.5/gpx/<id>/data */
698 gpx_data(&content, id);
699 break;
700 case 'e':
701 /* GET /api/0.5/gpx/<id>/details */
702 gpx_details(&content, id);
703 break;
706 break;
708 /* GET /api/0.5/<objtype>/<id>/full
709 * GET /api/0.5/<objtype>/<id>/history
710 * GET /api/0.5/<objtype>/<id>/relations */
712 case OSM_NODE_COMMAND:
713 switch (token[0]) {
714 case 'w':
715 /* GET /api/0.5/node/<id>/ways */
716 node_ways(&content, id);
717 break;
719 case OSM_WAY_COMMAND:
720 case OSM_RELATION_COMMAND:
721 switch (token[0]) {
722 case 'f':
723 objtype_full(&content, id, state);
724 break;
725 case 'h':
726 objtype_history(&content, id, state);
727 break;
728 case 'r':
729 objtype_relations(&content, id, state);
730 break;
732 break;
733 case OSM_NODES_PRE_PARSE:
734 switch (token[0]) {
735 case '?':
736 /* GET /api/0.5/<objtype>s?<objtype>s=<id>[,<id>...] */
737 parse_nodes(conn->arguments, &content);
738 break;
739 case 's':
740 /* GET /api/0.5/nodes/search?type=<type>&value=<value> */
741 parse_nodes_search(conn->arguments, &content);
742 break;
744 break;
746 case OSM_RELATIONS_PRE_PARSE:
747 switch (token[0]) {
748 case '?':
749 /* GET /api/0.5/<objtype>s?<objtype>s=<id>[,<id>...] */
750 parse_relations(conn->arguments, &content);
751 break;
752 case 's':
753 /* GET /api/0.5/relations/search?type=<type>&value=<value> */
754 parse_relations_search(conn->arguments, &content);
755 break;
757 break;
759 case OSM_WAYS_PRE_PARSE:
760 switch (token[0]) {
761 case '?':
762 /* GET /api/0.5/<objtype>s?<objtype>s=<id>[,<id>...] */
763 parse_ways(conn->arguments, &content);
764 break;
765 case 's':
766 /* GET /api/0.5/ways/search?type=<type>&value=<value> */
767 parse_ways_search(conn->arguments, &content);
768 break;
770 break;
777 /* Add the page ending
779 // cherokee_buffer_mrproper (&table);
780 // cherokee_buffer_add_str (buf, PAGE_FOOT);
781 //cherokee_buffer_add(&content, conn->request.buf+1, conn->request.len-1);
783 cherokee_buffer_add_str (buf, XMLHEADER);
784 cherokee_buffer_add_str (buf, XML(OSM, ""));
785 if (content.len > 0) {
786 cherokee_buffer_add_str (buf, XMLCONTINUE);
787 cherokee_buffer_add_buffer (buf, &content);
788 cherokee_buffer_mrproper (&content);
789 cherokee_buffer_add_str (buf, XMLCLOSE(OSM, ""));
790 } else
791 cherokee_buffer_add_str (buf, XMLCLOSESHORT);
796 ret_t
797 cherokee_handler_server_info_new (cherokee_handler_t **hdl, cherokee_connection_t *cnt, cherokee_module_props_t *props)
799 ret_t ret;
800 CHEROKEE_NEW_STRUCT (n, handler_server_info);
802 /* Init the base class object
804 cherokee_handler_init_base(HANDLER(n), cnt, HANDLER_PROPS(props), PLUGIN_INFO_HANDLER_PTR(server_info));
806 MODULE(n)->init = (handler_func_init_t) cherokee_handler_server_info_init;
807 MODULE(n)->free = (module_func_free_t) cherokee_handler_server_info_free;
808 HANDLER(n)->step = (handler_func_step_t) cherokee_handler_server_info_step;
809 HANDLER(n)->add_headers = (handler_func_add_headers_t) cherokee_handler_server_info_add_headers;
811 HANDLER(n)->support = hsupport_length;
814 /* Init
816 ret = cherokee_buffer_init (&n->buffer);
817 if (unlikely(ret != ret_ok))
818 return ret;
820 ret = cherokee_buffer_ensure_size (&n->buffer, 4*1024);
821 if (unlikely(ret != ret_ok))
822 return ret;
824 n->dbh = mapi_connect("localhost", 50000, "monetdb", "monetdb", "sql", NULL);
826 *hdl = HANDLER(n);
827 return ret_ok;
831 ret_t
832 cherokee_handler_server_info_free (cherokee_handler_server_info_t *hdl)
834 cherokee_buffer_mrproper (&hdl->buffer);
835 mapi_destroy(hdl->dbh);
837 return ret_ok;
841 ret_t
842 cherokee_handler_server_info_init (cherokee_handler_server_info_t *hdl)
844 cherokee_connection_parse_args (HANDLER_CONN(hdl));
845 server_info_build_page (hdl);
847 return ret_ok;
851 ret_t
852 cherokee_handler_server_info_step (cherokee_handler_server_info_t *hdl, cherokee_buffer_t *buffer)
854 if (hdl->buffer.len > 0) {
855 cherokee_buffer_add_buffer (buffer, &hdl->buffer);
856 cherokee_buffer_move_to_begin (&hdl->buffer, buffer->size);
857 if (hdl->buffer.len == 0)
858 return ret_eof_have_data;
860 return ret_ok;
861 } else
862 return ret_eagain;
866 ret_t
867 cherokee_handler_server_info_add_headers (cherokee_handler_server_info_t *hdl, cherokee_buffer_t *buffer)
869 cherokee_buffer_add_str (buffer, "Content-Type: text/xml; charset=utf-8"CRLF);
870 // cherokee_buffer_add_str (buffer, "Content-Disposition: attachment; filename=\"map.osm\""CRLF);
871 cherokee_buffer_add_va (buffer, "Content-Length: %d"CRLF, hdl->buffer.len);
872 return ret_ok;