1 #include <cherokee/common-internal.h>
2 #include <cherokee/cherokee.h>
6 #include "handler_osm.h"
7 #include "handler_osm_db.h"
8 #include "handler_osm_put.h"
9 #include "handler_osm_sql.h"
10 #include "handler_osm_delete.h"
12 static ret_t
result_node_last_id(cherokee_handler_osm_t
*hdl
, MapiHdl
*hdl1
, cherokee_buffer_t
*buf
) {
13 cherokee_buffer_add_va (buf
, "%d", mapi_get_last_id(*hdl1
));
17 static ret_t
node_update_or_insert (cherokee_handler_osm_t
*hdl
, MapiHdl
*hdl1
, cherokee_buffer_t
*buf
) {
18 if (mapi_rows_affected(*hdl1
) == 0)
24 static void do_members(cherokee_handler_osm_t
*hdl
, axlNode
*node
, unsigned long int relationid
, unsigned short int update
) {
26 if ((member
= axl_node_get_first_child(node
)) != NULL
) {
27 cherokee_buffer_t members_node
= CHEROKEE_BUF_INIT
;
28 cherokee_buffer_t members_way
= CHEROKEE_BUF_INIT
;
29 cherokee_buffer_t members_relation
= CHEROKEE_BUF_INIT
;
30 unsigned long int idx
= 0;
32 if (NODE_CMP_NAME (member
, "member") &&
33 axl_node_has_attribute(member
, "type") &&
34 axl_node_has_attribute(member
, "ref") &&
35 axl_node_has_attribute(member
, "role")) {
37 unsigned long int ref
= strtod(axl_node_get_attribute_value(member
, "ref"), NULL
);
38 if (errno
!= ERANGE
&& ref
> 0) {
39 const char *type
= axl_node_get_attribute_value(member
, "type");
40 const char *role
= axl_node_get_attribute_value(member
, "role");
42 if (strcmp(type
, "node") == 0) {
43 cherokee_buffer_add_va (&members_node
, "%lu, ", ref
);
44 cherokee_buffer_t sql1
= CHEROKEE_BUF_INIT
;
46 cherokee_buffer_add_va (&sql1
, "UPDATE relation_members_node SET to_node = %lu, role = '%s' WHERE relation = %lu AND idx = %lu", ref
, role
, relationid
, idx
);
48 if (update
== 0 || run_sql(hdl
, &sql1
, NULL
, node_update_or_insert
) == ret_error
) {
49 cherokee_buffer_mrproper(&sql1
);
50 cherokee_buffer_add_va (&sql1
, "INSERT INTO relation_members_node (relation, idx, to_node, role) VALUES (%lu, %lu, %lu, '%s')", relationid
, idx
, ref
, role
);
51 run_sql(hdl
, &sql1
, NULL
, NULL
);
53 cherokee_buffer_mrproper(&sql1
);
54 } else if (strcmp(type
, "way") == 0) {
55 cherokee_buffer_add_va (&members_way
, "%lu, ", ref
);
56 cherokee_buffer_t sql1
= CHEROKEE_BUF_INIT
;
58 cherokee_buffer_add_va (&sql1
, "UPDATE relation_members_way SET to_way = %lu, role = '%s' WHERE relation = %lu AND idx = %lu", ref
, role
, relationid
, idx
);
60 if (update
== 0 || run_sql(hdl
, &sql1
, NULL
, node_update_or_insert
) == ret_error
) {
61 cherokee_buffer_mrproper(&sql1
);
62 cherokee_buffer_add_va (&sql1
, "INSERT INTO relation_members_way (relation, idx, to_way, role) VALUES (%lu, %lu, %lu, '%s')", relationid
, idx
, ref
, role
);
63 run_sql(hdl
, &sql1
, NULL
, NULL
);
65 cherokee_buffer_mrproper(&sql1
);
66 } else if (strcmp(type
, "relation") == 0) {
67 cherokee_buffer_add_va (&members_relation
, "%lu, ", ref
);
68 cherokee_buffer_t sql1
= CHEROKEE_BUF_INIT
;
70 cherokee_buffer_add_va (&sql1
, "UPDATE relation_members_relation SET to_relation = %lu, role = '%s' WHERE relation = %lu AND idx = %lu", ref
, role
, relationid
, idx
);
72 if (update
== 0 || run_sql(hdl
, &sql1
, NULL
, node_update_or_insert
) == ret_error
) {
73 cherokee_buffer_mrproper(&sql1
);
74 cherokee_buffer_add_va (&sql1
, "INSERT INTO relation_members_relation (relation, idx, to_relation, role) VALUES (%lu, %lu, %lu, '%s')", relationid
, idx
, ref
, role
);
75 run_sql(hdl
, &sql1
, NULL
, NULL
);
77 cherokee_buffer_mrproper(&sql1
);
79 TRACE("osm", "%s: New type?\n", type
);
84 } while ((member
= axl_node_get_next(member
)) != NULL
);
86 if (members_node
.len
> 0) {
87 cherokee_buffer_t sql1
= CHEROKEE_BUF_INIT
;
88 cherokee_buffer_drop_ending(&members_node
, 2);
89 cherokee_buffer_add_va (&sql1
, "DELETE FROM relation_members_node WHERE relation = %lu AND to_node NOT IN (%s)", relationid
, members_node
.buf
);
90 run_sql(hdl
, &sql1
, NULL
, NULL
);
91 cherokee_buffer_mrproper(&sql1
);
93 cherokee_buffer_mrproper(&members_node
);
95 if (members_way
.len
> 0) {
96 cherokee_buffer_t sql1
= CHEROKEE_BUF_INIT
;
97 cherokee_buffer_drop_ending(&members_way
, 2);
98 cherokee_buffer_add_va (&sql1
, "DELETE FROM relation_members_way WHERE relation = %lu AND to_way NOT IN (%s)", relationid
, members_way
.buf
);
99 run_sql(hdl
, &sql1
, NULL
, NULL
);
100 cherokee_buffer_mrproper(&sql1
);
102 cherokee_buffer_mrproper(&members_way
);
104 if (members_relation
.len
> 0) {
105 cherokee_buffer_t sql1
= CHEROKEE_BUF_INIT
;
106 cherokee_buffer_drop_ending(&members_relation
, 2);
107 cherokee_buffer_add_va (&sql1
, "DELETE FROM relation_members_relation WHERE relation = %lu AND to_relation NOT IN (%s)", relationid
, members_relation
.buf
);
108 run_sql(hdl
, &sql1
, NULL
, NULL
);
109 cherokee_buffer_mrproper(&sql1
);
111 cherokee_buffer_mrproper(&members_relation
);
117 static void do_nds(cherokee_handler_osm_t
*hdl
, axlNode
*node
, unsigned long int wayid
, unsigned short int update
) {
119 if ((nd
= axl_node_get_first_child(node
)) != NULL
) {
120 cherokee_buffer_t nds
= CHEROKEE_BUF_INIT
;
121 unsigned long int idx
= 0;
123 if (NODE_CMP_NAME (nd
, "nd") &&
124 axl_node_has_attribute(nd
, "ref")) {
126 unsigned long int ref
= strtod(axl_node_get_attribute_value(nd
, "ref"), NULL
);
127 if (errno
!= ERANGE
&& ref
> 0) {
128 cherokee_buffer_add_va (&nds
, "%lu, ", ref
);
130 cherokee_buffer_t sql1
= CHEROKEE_BUF_INIT
;
132 cherokee_buffer_add_va (&sql1
, "UPDATE way_nds SET to_node = %lu WHERE way = %lu AND idx = %lu", ref
, wayid
, idx
);
134 if (update
== 0 || run_sql(hdl
, &sql1
, NULL
, node_update_or_insert
) == ret_error
) {
135 cherokee_buffer_mrproper(&sql1
);
136 cherokee_buffer_add_va (&sql1
, "INSERT INTO way_nds (way, idx, to_node) VALUES (%lu, %lu, %lu)", wayid
, idx
, ref
);
137 run_sql(hdl
, &sql1
, NULL
, NULL
);
139 cherokee_buffer_mrproper(&sql1
);
143 } while ((nd
= axl_node_get_next(nd
)) != NULL
);
146 cherokee_buffer_t sql1
= CHEROKEE_BUF_INIT
;
147 cherokee_buffer_drop_ending(&nds
, 2);
148 cherokee_buffer_add_va (&sql1
, "DELETE FROM way_nds WHERE relation = %lu AND to_node NOT IN (%s)", wayid
, nds
.buf
);
149 run_sql(hdl
, &sql1
, NULL
, NULL
);
150 cherokee_buffer_mrproper(&sql1
);
153 cherokee_buffer_mrproper(&nds
);
157 static void do_tags(cherokee_handler_osm_t
*hdl
, axlNode
*node
, unsigned long int nodeid
, unsigned short int update
, char *create_sql
, char *update_sql
, char *delete_sql
) {
159 if ((tag
= axl_node_get_first_child(node
)) != NULL
) {
160 cherokee_buffer_t keys
= CHEROKEE_BUF_INIT
;
162 if (NODE_CMP_NAME (tag
, "tag") &&
163 axl_node_has_attribute(tag
, "k") &&
164 axl_node_has_attribute(tag
, "v")) {
165 const char * key
= axl_node_get_attribute_value(tag
, "k");
166 size_t keylen
= strlen(key
);
168 if (keylen
> 0 && keylen
< 256) {
169 const char * value
= axl_node_get_attribute_value(tag
, "v");
170 size_t valuelen
= strlen(value
);
171 cherokee_buffer_add_va (&keys
, "\'%s\', ", key
);
173 if (valuelen
> 0 && valuelen
< 256) {
174 cherokee_buffer_t sql1
= CHEROKEE_BUF_INIT
;
176 cherokee_buffer_add_va (&sql1
, update_sql
,
182 if (update
== 0 || run_sql(hdl
, &sql1
, NULL
, node_update_or_insert
) == ret_error
) {
183 cherokee_buffer_mrproper(&sql1
);
184 cherokee_buffer_add_va (&sql1
, create_sql
,
188 run_sql(hdl
, &sql1
, NULL
, NULL
);
190 cherokee_buffer_mrproper(&sql1
);
194 } while ((tag
= axl_node_get_next(tag
)) != NULL
);
197 cherokee_buffer_t sql1
= CHEROKEE_BUF_INIT
;
198 cherokee_buffer_drop_ending(&keys
, 2);
199 cherokee_buffer_add_va (&sql1
, delete_sql
, nodeid
, keys
.buf
);
200 run_sql(hdl
, &sql1
, NULL
, NULL
);
201 cherokee_buffer_mrproper(&sql1
);
204 cherokee_buffer_mrproper(&keys
);
209 node_exists(cherokee_handler_osm_t
*hdl
, osm_state_delete_t type
, unsigned long int nodeid
) {
211 cherokee_buffer_t sql1
= CHEROKEE_BUF_INIT
;
212 cherokee_buffer_t tmp
= CHEROKEE_BUF_INIT
;
215 case OSM_DELETE_NODE_COMMAND
:
216 cherokee_buffer_add_va (&sql1
, SQL_NODE_EXIST
, nodeid
);
219 case OSM_DELETE_WAY_COMMAND
:
220 cherokee_buffer_add_va (&sql1
, SQL_WAY_EXIST
, nodeid
);
223 case OSM_DELETE_RELATION_COMMAND
:
224 cherokee_buffer_add_va (&sql1
, SQL_RELATION_EXIST
, nodeid
);
232 run_sql(hdl
, &sql1
, &tmp
, NULL
);
236 cherokee_buffer_mrproper(&sql1
);
237 cherokee_buffer_mrproper(&tmp
);
243 create_node(cherokee_handler_osm_t
*hdl
, axlNode
* node
, osm_state_delete_t type
, unsigned long int nodeid
, const char *username
, short int timestamp
) {
244 cherokee_connection_t
*conn
= HANDLER_CONN(hdl
);
245 cherokee_buffer_t
*buf
= &hdl
->buffer
;
248 case OSM_DELETE_NODE_COMMAND
: {
249 if (axl_node_has_attribute(node
, "lat") &&
250 axl_node_has_attribute(node
, "lon")) {
252 lat
= strtod(axl_node_get_attribute_value(node
, "lat"), NULL
);
253 if (errno
== ERANGE
) {
254 conn
->error_code
= http_bad_request
;
258 lon
= strtod(axl_node_get_attribute_value(node
, "lon"), NULL
);
259 if (errno
== ERANGE
) {
260 conn
->error_code
= http_bad_request
;
263 /* TODO: more error checking */
265 cherokee_buffer_t sql1
= CHEROKEE_BUF_INIT
;
268 if (timestamp
== 1 && axl_node_has_attribute(node
, "timestamp")) {
269 cherokee_buffer_add_va (&sql1
, SQL_NODE_CREATE
, lon
, lat
, username
, "'", axl_node_get_attribute_value(node
, "timestamp"), "'");
271 cherokee_buffer_add_va (&sql1
, SQL_NODE_CREATE
, lon
, lat
, username
, SQL_NOW
);
274 if (timestamp
== 1 && axl_node_has_attribute(node
, "timestamp")) {
275 cherokee_buffer_add_va (&sql1
, SQL_NODE_CREATE_BY_ID
, lon
, lat
, username
, "'", axl_node_get_attribute_value(node
, "timestamp"), "'", nodeid
);
277 cherokee_buffer_add_va (&sql1
, SQL_NODE_CREATE_BY_ID
, lon
, lat
, username
, SQL_NOW
, nodeid
);
280 run_sql(hdl
, &sql1
, buf
, result_node_last_id
);
281 cherokee_buffer_mrproper(&sql1
);
283 testid
= strtol(buf
->buf
, (char **) NULL
, 10);
284 if (errno
!= ERANGE
&& testid
> 0) {
285 do_tags(hdl
, node
, testid
, 0, SQL_NODE_CREATE_NODE_TAG
, SQL_NODE_UPDATE_NODE_TAG
, SQL_NODE_DELETE_NODE_TAG
);
294 case OSM_DELETE_WAY_COMMAND
: {
295 cherokee_buffer_t sql1
= CHEROKEE_BUF_INIT
;
296 cherokee_buffer_add_va (&sql1
, SQL_WAY_CREATE
, username
);
297 run_sql(hdl
, &sql1
, buf
, result_node_last_id
);
298 cherokee_buffer_mrproper(&sql1
);
301 testid
= strtol(buf
->buf
, (char **) NULL
, 10);
302 if (errno
!= ERANGE
&& testid
> 0) {
303 do_tags(hdl
, node
, testid
, 0, SQL_WAY_CREATE_NODE_TAG
, SQL_WAY_UPDATE_NODE_TAG
, SQL_WAY_DELETE_NODE_TAG
);
304 do_nds(hdl
, node
, testid
, 0); /* this sequence otherwise we screw up type= */
312 case OSM_DELETE_RELATION_COMMAND
: {
313 cherokee_buffer_t sql1
= CHEROKEE_BUF_INIT
;
314 cherokee_buffer_add_va (&sql1
, SQL_RELATION_CREATE
, username
);
315 run_sql(hdl
, &sql1
, buf
, result_node_last_id
);
316 cherokee_buffer_mrproper(&sql1
);
319 testid
= strtol(buf
->buf
, (char **) NULL
, 10);
320 if (errno
!= ERANGE
&& testid
> 0) {
321 do_members(hdl
, node
, testid
, 0);
322 do_tags(hdl
, node
, testid
, 0, SQL_RELATION_CREATE_NODE_TAG
, SQL_RELATION_UPDATE_NODE_TAG
, SQL_RELATION_DELETE_NODE_TAG
);
338 update_node(cherokee_handler_osm_t
*hdl
, axlNode
* node
, osm_state_delete_t type
, unsigned long int nodeid
, const char *username
, short int timestamp
) {
339 cherokee_connection_t
*conn
= HANDLER_CONN(hdl
);
341 if (axl_node_has_attribute_value(node
, "visible", "false")) {
342 /* the user wants to delete stuff by updating, that is nice
343 * but we will not update. Instead we do what the user request:
346 return delete_object_by_id(hdl
, nodeid
, type
);
349 case OSM_DELETE_NODE_COMMAND
: {
350 if (axl_node_has_attribute(node
, "lat") &&
351 axl_node_has_attribute(node
, "lon")) {
353 lat
= strtod(axl_node_get_attribute_value(node
, "lat"), NULL
);
354 if (errno
== ERANGE
) {
355 conn
->error_code
= http_bad_request
;
359 lon
= strtod(axl_node_get_attribute_value(node
, "lon"), NULL
);
360 if (errno
== ERANGE
) {
361 conn
->error_code
= http_bad_request
;
364 cherokee_buffer_t sql1
= CHEROKEE_BUF_INIT
;
365 if (timestamp
== 1 && axl_node_has_attribute(node
, "timestamp")) {
366 cherokee_buffer_add_va (&sql1
, SQL_NODE_UPDATE_BY_ID
, lon
, lat
, username
,
367 "'", axl_node_get_attribute_value(node
, "timestamp"), "'", nodeid
);
369 cherokee_buffer_add_va (&sql1
, SQL_NODE_UPDATE_BY_ID
, lon
, lat
, username
, SQL_NOW
, nodeid
);
371 run_sql(hdl
, &sql1
, NULL
, NULL
);
372 cherokee_buffer_mrproper(&sql1
);
374 do_tags(hdl
, node
, nodeid
, 1, SQL_NODE_CREATE_NODE_TAG
, SQL_NODE_UPDATE_NODE_TAG
, SQL_NODE_DELETE_NODE_TAG
);
381 case OSM_DELETE_WAY_COMMAND
: {
382 cherokee_buffer_t sql1
= CHEROKEE_BUF_INIT
;
383 if (timestamp
== 1 && axl_node_has_attribute(node
, "timestamp")) {
384 cherokee_buffer_add_va (&sql1
, SQL_WAY_UPDATE
, username
,
385 "'", axl_node_get_attribute_value(node
, "timestamp"), "'", nodeid
);
387 cherokee_buffer_add_va (&sql1
, SQL_WAY_UPDATE
, username
, SQL_NOW
, nodeid
);
389 run_sql(hdl
, &sql1
, NULL
, NULL
);
390 cherokee_buffer_mrproper(&sql1
);
392 do_tags(hdl
, node
, nodeid
, 1, SQL_WAY_CREATE_NODE_TAG
, SQL_WAY_UPDATE_NODE_TAG
, SQL_WAY_DELETE_NODE_TAG
);
393 do_nds(hdl
, node
, nodeid
, 1); /* this sequence otherwise we screw up type = */
398 case OSM_DELETE_RELATION_COMMAND
: {
399 cherokee_buffer_t sql1
= CHEROKEE_BUF_INIT
;
400 if (timestamp
== 1 && axl_node_has_attribute(node
, "timestamp")) {
401 cherokee_buffer_add_va (&sql1
, SQL_RELATION_UPDATE
, username
,
402 "'", axl_node_get_attribute_value(node
, "timestamp"), "'", nodeid
);
404 cherokee_buffer_add_va (&sql1
, SQL_RELATION_UPDATE
, username
, SQL_NOW
, nodeid
);
406 run_sql(hdl
, &sql1
, NULL
, NULL
);
407 cherokee_buffer_mrproper(&sql1
);
409 do_members(hdl
, node
, nodeid
, 1);
410 do_tags(hdl
, node
, nodeid
, 1, SQL_RELATION_CREATE_NODE_TAG
, SQL_RELATION_UPDATE_NODE_TAG
, SQL_RELATION_DELETE_NODE_TAG
);
428 cherokee_handler_osm_init_put (cherokee_handler_osm_t
*hdl
)
432 cherokee_buffer_t post
= CHEROKEE_BUF_INIT
;
433 cherokee_connection_t
*conn
= HANDLER_CONN(hdl
);
437 /* Check for the post info
439 cherokee_post_get_len (&conn
->post
, &postl
);
440 if (postl
<= 0 || postl
>= (INT_MAX
-1)) {
441 conn
->error_code
= http_bad_request
;
446 /* Process line per line
448 cherokee_post_walk_read (&conn
->post
, &post
, (cuint_t
) postl
);
450 TRACE("post", "%s\n", post
.buf
);
452 doc
= axl_doc_parse (post
.buf
, post
.len
, &error
);
455 printf ("Error found: %s\n", axl_error_get (error
));
456 axl_error_free (error
);
460 axlNode
* node
= axl_doc_get_root (doc
);
461 node
= axl_node_get_first_child (node
);
464 /* het mooiste zou zijn om het onderstaande in twee functies te zetten
466 * Als dat gebeurd is kan hier (of in de 'update' code gechecked worden
467 * op 'root' of op normale user en aan de hand daarvan weer switchen op
468 * empty == create of full == update)
470 cherokee_buffer_t sql1
= CHEROKEE_BUF_INIT
;
471 cherokee_buffer_add_str (&sql1
, SQL_TRANSACTION_START
);
472 run_sql(hdl
, &sql1
, &hdl
->buffer
, NULL
);
473 cherokee_buffer_mrproper(&sql1
);
475 isroot
= (cherokee_buffer_cmp_str(conn
->realm_ref
,"root") == 0);
477 while (node
!= NULL
&& ret
== ret_ok
) {
478 const char *username
= NULL
;
479 unsigned long int nodeid
= 0;
480 osm_state_delete_t type
;
482 if (axl_node_has_attribute(node
, "id")) {
483 const char *id
= axl_node_get_attribute_value(node
, "id");
484 nodeid
= strtoul(id
, (char **) NULL
, 10);
485 TRACE("osm", "%lu\n", nodeid
);
489 username
= axl_node_get_attribute_value(node
, "user");
491 username
= conn
->realm_ref
->buf
;
494 if (NODE_CMP_NAME (node
, "node")) {
495 type
= OSM_DELETE_NODE_COMMAND
;
496 } else if (NODE_CMP_NAME (node
, "way")) {
497 type
= OSM_DELETE_WAY_COMMAND
;
498 } else if (NODE_CMP_NAME (node
, "relation")) {
499 type
= OSM_DELETE_RELATION_COMMAND
;
505 if (nodeid
> 0 && node_exists(hdl
, type
, nodeid
)) {
507 ret
= update_node(hdl
, node
, type
, nodeid
, username
, isroot
);
510 ret
= create_node(hdl
, node
, type
, nodeid
, username
, isroot
);
513 node
= axl_node_get_next(node
);
517 cherokee_buffer_add_str (&sql1
, SQL_TRANSACTION_ROLLBACK
);
518 run_sql(hdl
, &sql1
, &hdl
->buffer
, NULL
);
519 cherokee_buffer_mrproper(&sql1
);
521 cherokee_buffer_add_str (&sql1
, SQL_TRANSACTION_COMMIT
);
522 run_sql(hdl
, &sql1
, &hdl
->buffer
, NULL
);
523 cherokee_buffer_mrproper(&sql1
);
529 cherokee_buffer_mrproper (&post
);