1 /*
2 / spatialite_osm_filter
3 /
4 / a tool loading OSM-XML maps into a SpatiaLite DB
5 /
6 / version 1.0, 2011 October 31
7 /
8 / Author: Sandro Furieri a.furieri@lqt.it
9 /
10 / Copyright (C) 2011  Alessandro Furieri
11 /
12 /    This program is free software: you can redistribute it and/or modify
13 /    it under the terms of the GNU General Public License as published by
14 /    the Free Software Foundation, either version 3 of the License, or
15 /    (at your option) any later version.
16 /
17 /    This program is distributed in the hope that it will be useful,
18 /    but WITHOUT ANY WARRANTY; without even the implied warranty of
19 /    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 /    GNU General Public License for more details.
21 /
22 /    You should have received a copy of the GNU General Public License
23 /    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24 /
25 */
26 
27 #if defined(_WIN32) && !defined(__MINGW32__)
28 /* MSVC strictly requires this include [off_t] */
29 #include <sys/types.h>
30 #endif
31 
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
35 
36 #if defined(_WIN32) && !defined(__MINGW32__)
37 #include "config-msvc.h"
38 #else
39 #include "config.h"
40 #endif
41 
42 #ifdef SPATIALITE_AMALGAMATION
43 #include <spatialite/sqlite3.h>
44 #else
45 #include <sqlite3.h>
46 #endif
47 
48 #include <spatialite/gaiageo.h>
49 #include <spatialite.h>
50 
51 
52 #define ARG_NONE		0
53 #define ARG_OSM_PATH	1
54 #define ARG_DB_PATH		2
55 #define ARG_CACHE_SIZE	3
56 #define ARG_MASK_PATH	4
57 
58 #if defined(_WIN32) && !defined(__MINGW32__)
59 #define strcasecmp	_stricmp
60 #endif /* not WIN32 */
61 
62 static char *
clean_xml(const char * in)63 clean_xml (const char *in)
64 {
65 /* well formatting XML text strings */
66     int len = 0;
67     char *buf;
68     char *p_o;
69     const char *p_i = in;
70     while (*p_i != '\0')
71       {
72 	  /* calculating the output len */
73 	  if (*p_i == '"')
74 	    {
75 		len += 6;
76 		p_i++;
77 		continue;
78 	    }
79 	  if (*p_i == '\'')
80 	    {
81 		len += 6;
82 		p_i++;
83 		continue;
84 	    }
85 	  if (*p_i == '&')
86 	    {
87 		len += 5;
88 		p_i++;
89 		continue;
90 	    }
91 	  if (*p_i == '<')
92 	    {
93 		len += 4;
94 		p_i++;
95 		continue;
96 	    }
97 	  if (*p_i == '>')
98 	    {
99 		len += 4;
100 		p_i++;
101 		continue;
102 	    }
103 	  len++;
104 	  p_i++;
105       }
106 
107     buf = malloc (len + 1);
108     p_o = buf;
109     p_i = in;
110     while (*p_i != '\0')
111       {
112 	  if (*p_i == '"')
113 	    {
114 		*p_o++ = '&';
115 		*p_o++ = 'q';
116 		*p_o++ = 'u';
117 		*p_o++ = 'o';
118 		*p_o++ = 't';
119 		*p_o++ = ';';
120 		p_i++;
121 		continue;
122 	    }
123 	  if (*p_i == '\'')
124 	    {
125 		*p_o++ = '&';
126 		*p_o++ = 'a';
127 		*p_o++ = 'p';
128 		*p_o++ = 'o';
129 		*p_o++ = 's';
130 		*p_o++ = ';';
131 		p_i++;
132 		continue;
133 	    }
134 	  if (*p_i == '&')
135 	    {
136 		*p_o++ = '&';
137 		*p_o++ = 'a';
138 		*p_o++ = 'm';
139 		*p_o++ = 'p';
140 		*p_o++ = ';';
141 		p_i++;
142 		continue;
143 	    }
144 	  if (*p_i == '<')
145 	    {
146 		*p_o++ = '&';
147 		*p_o++ = 'l';
148 		*p_o++ = 't';
149 		*p_o++ = ';';
150 		p_i++;
151 		continue;
152 	    }
153 	  if (*p_i == '>')
154 	    {
155 		*p_o++ = '&';
156 		*p_o++ = 'g';
157 		*p_o++ = 't';
158 		*p_o++ = ';';
159 		p_i++;
160 		continue;
161 	    }
162 	  *p_o++ = *p_i++;
163       }
164     *p_o = '\0';
165     return buf;
166 }
167 
168 static int
do_output_nodes(FILE * out,sqlite3 * handle)169 do_output_nodes (FILE * out, sqlite3 * handle)
170 {
171 /* exporting any OSM node */
172     char sql[1024];
173     int ret;
174     int first;
175     int close_node;
176     sqlite3_stmt *node_query = NULL;
177     sqlite3_stmt *query = NULL;
178 
179 /* preparing the QUERY filtered-NODES statement */
180     strcpy (sql, "SELECT node_id FROM osm_nodes WHERE filtered = 1");
181     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &node_query, NULL);
182     if (ret != SQLITE_OK)
183       {
184 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
185 	  return 0;
186       }
187 
188 /* preparing the QUERY NODES statement */
189     strcpy (sql, "SELECT n.node_id, n.version, n.timestamp, ");
190     strcat (sql, "n.uid, n.user, n.changeset, ST_X(n.Geometry), ");
191     strcat (sql, "ST_Y(n.Geometry), t.k, t.v ");
192     strcat (sql, "FROM osm_nodes AS n ");
193     strcat (sql, "LEFT JOIN osm_node_tags AS t ON (t.node_id = n.node_id) ");
194     strcat (sql, "WHERE n.node_id = ? ");
195     strcat (sql, "ORDER BY n.node_id, t.sub");
196     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &query, NULL);
197     if (ret != SQLITE_OK)
198       {
199 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
200 	  goto stop;
201       }
202 
203     while (1)
204       {
205 	  /* scrolling the result set */
206 	  ret = sqlite3_step (node_query);
207 	  if (ret == SQLITE_DONE)
208 	    {
209 		/* there are no more rows to fetch - we can stop looping */
210 		break;
211 	    }
212 	  if (ret == SQLITE_ROW)
213 	    {
214 		/* ok, we've just fetched a valid row */
215 		sqlite3_int64 id = sqlite3_column_int64 (node_query, 0);
216 
217 		sqlite3_reset (query);
218 		sqlite3_clear_bindings (query);
219 		sqlite3_bind_int64 (query, 1, id);
220 		first = 1;
221 		close_node = 0;
222 		while (1)
223 		  {
224 		      /* scrolling the result set */
225 		      ret = sqlite3_step (query);
226 		      if (ret == SQLITE_DONE)
227 			{
228 			    /* there are no more rows to fetch - we can stop looping */
229 			    break;
230 			}
231 		      if (ret == SQLITE_ROW)
232 			{
233 			    /* ok, we've just fetched a valid row */
234 			    sqlite3_int64 id = sqlite3_column_int64 (query, 0);
235 			    int version = sqlite3_column_int (query, 1);
236 			    const char *p_timestamp =
237 				(const char *) sqlite3_column_text (query, 2);
238 			    int uid = sqlite3_column_int (query, 3);
239 			    const char *p_user =
240 				(const char *) sqlite3_column_text (query, 4);
241 			    const char *p_changeset =
242 				(const char *) sqlite3_column_text (query, 5);
243 			    double x = sqlite3_column_double (query, 6);
244 			    double y = sqlite3_column_double (query, 7);
245 			    char *k = NULL;
246 			    char *v = NULL;
247 			    if (sqlite3_column_type (query, 8) != SQLITE_NULL)
248 				k = clean_xml ((const char *)
249 					       sqlite3_column_text (query, 8));
250 			    if (sqlite3_column_type (query, 9) != SQLITE_NULL)
251 				v = clean_xml ((const char *)
252 					       sqlite3_column_text (query, 9));
253 
254 			    if (first)
255 			      {
256 				  /* first NODE row */
257 				  char *timestamp =
258 				      p_timestamp ? clean_xml (p_timestamp) :
259 				      NULL;
260 				  char *changeset =
261 				      p_changeset ? clean_xml (p_changeset) :
262 				      NULL;
263 				  char *user =
264 				      p_user ? clean_xml (p_user) : NULL;
265 				  first = 0;
266 #if defined(_WIN32) || defined(__MINGW32__)
267 /* CAVEAT - M$ runtime doesn't supports %lld for 64 bits */
268 				  fprintf (out, "\t<node id=\"%I64d\"", id);
269 #else
270 				  fprintf (out, "\t<node id=\"%lld\"", id);
271 #endif
272 				  if (user)
273 				    {
274 					fprintf (out, " user=\"%s\"", user);
275 					free (user);
276 				    }
277 				  if (changeset)
278 				    {
279 					fprintf (out, " changeset=\"%s\"",
280 						 changeset);
281 					free (changeset);
282 				    }
283 				  if (timestamp)
284 				    {
285 					fprintf (out, " timestamp=\"%s\"",
286 						 timestamp);
287 					free (timestamp);
288 				    }
289 				  if (!version)
290 				      version = 1;
291 				  fprintf (out, " version=\"%d\"", version);
292 				  fprintf (out,
293 					   " lat=\"%1.7f\" lon=\"%1.7f\" uid=\"%d\" ",
294 					   y, x, uid);
295 				  if (k == NULL && v == NULL)
296 				      fprintf (out, "/>\n");
297 				  else
298 				      fprintf (out, ">\n");
299 			      }
300 			    if (k != NULL && v != NULL)
301 			      {
302 				  /* NODE tag */
303 				  fprintf (out,
304 					   "\t\t<tag k=\"%s\" v=\"%s\"/>\n", k,
305 					   v);
306 				  close_node = 1;
307 			      }
308 			    if (k)
309 				free (k);
310 			    if (v)
311 				free (v);
312 			}
313 		      else
314 			{
315 			    /* some unexpected error occurred */
316 			    fprintf (stderr, "sqlite3_step() error: %s\n",
317 				     sqlite3_errmsg (handle));
318 			    goto stop;
319 			}
320 		  }
321 		if (close_node)
322 		    fprintf (out, "\t</node>\n");
323 	    }
324 	  else
325 	    {
326 		/* some unexpected error occurred */
327 		fprintf (stderr, "sqlite3_step() error: %s\n",
328 			 sqlite3_errmsg (handle));
329 		goto stop;
330 	    }
331       }
332     sqlite3_finalize (node_query);
333     sqlite3_finalize (query);
334 
335     return 1;
336 
337   stop:
338     sqlite3_finalize (node_query);
339     if (query)
340 	sqlite3_finalize (query);
341     return 0;
342 }
343 
344 static int
do_output_ways(FILE * out,sqlite3 * handle)345 do_output_ways (FILE * out, sqlite3 * handle)
346 {
347 /* exporting any OSM way */
348     char sql[1024];
349     int ret;
350     int first;
351     sqlite3_stmt *way_query = NULL;
352     sqlite3_stmt *query = NULL;
353     sqlite3_stmt *query_tag = NULL;
354 
355 /* preparing the QUERY filtered-WAYS statement */
356     strcpy (sql, "SELECT way_id FROM osm_ways WHERE filtered = 1");
357     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &way_query, NULL);
358     if (ret != SQLITE_OK)
359       {
360 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
361 	  return 0;
362       }
363 
364 /* preparing the QUERY WAY/NODES statement */
365     strcpy (sql, "SELECT w.way_id, w.version, w.timestamp, w.uid, ");
366     strcat (sql, "w.user, w.changeset, n.node_id ");
367     strcat (sql, "FROM osm_ways AS w ");
368     strcat (sql, "JOIN osm_way_refs AS n ON (n.way_id = w.way_id) ");
369     strcat (sql, "WHERE w.way_id = ? ");
370     strcat (sql, "ORDER BY w.way_id, n.sub");
371     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &query, NULL);
372     if (ret != SQLITE_OK)
373       {
374 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
375 	  goto stop;
376       }
377 
378 /* preparing the QUERY WAY/TAGS statement */
379     strcpy (sql, "SELECT t.k, t.v ");
380     strcat (sql, "FROM osm_ways AS w ");
381     strcat (sql, "JOIN osm_way_tags AS t ON (t.way_id = w.way_id) ");
382     strcat (sql, "WHERE w.way_id = ? ");
383     strcat (sql, "ORDER BY w.way_id, t.sub");
384     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &query_tag, NULL);
385     if (ret != SQLITE_OK)
386       {
387 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
388 	  goto stop;
389       }
390 
391     while (1)
392       {
393 	  /* scrolling the result set */
394 	  ret = sqlite3_step (way_query);
395 	  if (ret == SQLITE_DONE)
396 	    {
397 		/* there are no more rows to fetch - we can stop looping */
398 		break;
399 	    }
400 	  if (ret == SQLITE_ROW)
401 	    {
402 		/* ok, we've just fetched a valid row */
403 		sqlite3_int64 id = sqlite3_column_int64 (way_query, 0);
404 
405 		sqlite3_reset (query);
406 		sqlite3_clear_bindings (query);
407 		sqlite3_bind_int64 (query, 1, id);
408 		first = 1;
409 		while (1)
410 		  {
411 		      /* scrolling the result set */
412 		      ret = sqlite3_step (query);
413 		      if (ret == SQLITE_DONE)
414 			{
415 			    /* there are no more rows to fetch - we can stop looping */
416 			    break;
417 			}
418 		      if (ret == SQLITE_ROW)
419 			{
420 			    /* ok, we've just fetched a valid row */
421 			    sqlite3_int64 id = sqlite3_column_int64 (query, 0);
422 			    int version = sqlite3_column_int (query, 1);
423 			    const char *p_timestamp =
424 				(const char *) sqlite3_column_text (query, 2);
425 			    int uid = sqlite3_column_int (query, 3);
426 			    const char *p_user =
427 				(const char *) sqlite3_column_text (query, 4);
428 			    const char *p_changeset =
429 				(const char *) sqlite3_column_text (query, 5);
430 			    sqlite3_int64 node_id =
431 				sqlite3_column_int64 (query, 6);
432 
433 			    if (first)
434 			      {
435 				  /* first WAY row */
436 				  char *timestamp =
437 				      p_timestamp ? clean_xml (p_timestamp) :
438 				      NULL;
439 				  char *changeset =
440 				      p_changeset ? clean_xml (p_changeset) :
441 				      NULL;
442 				  char *user = NULL;
443 				  if (p_user)
444 				      user = clean_xml (p_user);
445 				  first = 0;
446 #if defined(_WIN32) || defined(__MINGW32__)
447 /* CAVEAT - M$ runtime doesn't supports %lld for 64 bits */
448 				  fprintf (out, "\t<way id=\"%I64d\"", id);
449 #else
450 				  fprintf (out, "\t<way id=\"%lld\"", id);
451 #endif
452 				  if (user)
453 				    {
454 					fprintf (out, " user=\"%s\"", user);
455 					free (user);
456 				    }
457 				  if (changeset)
458 				    {
459 					fprintf (out, " changeset=\"%s\"",
460 						 changeset);
461 					free (changeset);
462 				    }
463 				  if (timestamp)
464 				    {
465 					fprintf (out, " timestamp=\"%s\"",
466 						 timestamp);
467 					free (timestamp);
468 				    }
469 				  if (!version)
470 				      version = 1;
471 				  fprintf (out, " version=\"%d\"", version);
472 				  fprintf (out, " uid=\"%d\" >\n", uid);
473 			      }
474 			    /* NODE REF tag */
475 #if defined(_WIN32) || defined(__MINGW32__)
476 /* CAVEAT - M$ runtime doesn't supports %lld for 64 bits */
477 			    fprintf (out, "\t\t<nd ref=\"%I64d\"/>\n", node_id);
478 #else
479 			    fprintf (out, "\t\t<nd ref=\"%lld\"/>\n", node_id);
480 #endif
481 			}
482 		      else
483 			{
484 			    /* some unexpected error occurred */
485 			    fprintf (stderr, "sqlite3_step() error: %s\n",
486 				     sqlite3_errmsg (handle));
487 			    goto stop;
488 			}
489 		  }
490 		if (!first)
491 		  {
492 		      /* exporting WAY tags */
493 		      sqlite3_reset (query_tag);
494 		      sqlite3_clear_bindings (query_tag);
495 		      sqlite3_bind_int64 (query_tag, 1, id);
496 		      while (1)
497 			{
498 			    /* scrolling the result set */
499 			    ret = sqlite3_step (query_tag);
500 			    if (ret == SQLITE_DONE)
501 			      {
502 				  /* there are no more rows to fetch - we can stop looping */
503 				  break;
504 			      }
505 			    if (ret == SQLITE_ROW)
506 			      {
507 				  /* ok, we've just fetched a valid row */
508 				  char *k =
509 				      clean_xml ((const char *)
510 						 sqlite3_column_text (query_tag,
511 								      0));
512 				  char *v =
513 				      clean_xml ((const char *)
514 						 sqlite3_column_text (query_tag,
515 								      1));
516 				  fprintf (out,
517 					   "\t\t<tag k=\"%s\" v=\"%s\"/>\n", k,
518 					   v);
519 				  free (k);
520 				  free (v);
521 			      }
522 			    else
523 			      {
524 				  /* some unexpected error occurred */
525 				  fprintf (stderr, "sqlite3_step() error: %s\n",
526 					   sqlite3_errmsg (handle));
527 				  goto stop;
528 			      }
529 			}
530 		  }
531 		fprintf (out, "\t</way>\n");
532 	    }
533 	  else
534 	    {
535 		/* some unexpected error occurred */
536 		fprintf (stderr, "sqlite3_step() error: %s\n",
537 			 sqlite3_errmsg (handle));
538 		goto stop;
539 	    }
540       }
541     sqlite3_finalize (way_query);
542     sqlite3_finalize (query);
543     sqlite3_finalize (query_tag);
544 
545     return 1;
546 
547   stop:
548     sqlite3_finalize (way_query);
549     if (query)
550 	sqlite3_finalize (query);
551     if (query_tag)
552 	sqlite3_finalize (query_tag);
553     return 0;
554 }
555 
556 static int
do_output_relations(FILE * out,sqlite3 * handle)557 do_output_relations (FILE * out, sqlite3 * handle)
558 {
559 /* exporting any OSM relation */
560     char sql[1024];
561     int ret;
562     int first;
563     sqlite3_stmt *rel_query = NULL;
564     sqlite3_stmt *query_nd = NULL;
565     sqlite3_stmt *query_way = NULL;
566     sqlite3_stmt *query_rel = NULL;
567     sqlite3_stmt *query_tag = NULL;
568 
569 /* preparing the QUERY filtered-RELATIONS statement */
570     strcpy (sql, "SELECT rel_id FROM osm_relations WHERE filtered = 1");
571     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &rel_query, NULL);
572     if (ret != SQLITE_OK)
573       {
574 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
575 	  return 0;
576       }
577 
578 /* preparing the QUERY RELATION/NODES statement */
579     strcpy (sql, "SELECT r.rel_id, r.version, r.timestamp, r.uid, ");
580     strcat (sql, "r.user, r.changeset, n.role, n.ref ");
581     strcat (sql, "FROM osm_relations AS r ");
582     strcat (sql,
583 	    "JOIN osm_relation_refs AS n ON (n.type = 'N' AND n.rel_id = r.rel_id) ");
584     strcat (sql, "WHERE r.rel_id = ? ");
585     strcat (sql, "ORDER BY r.rel_id, n.sub");
586     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &query_nd, NULL);
587     if (ret != SQLITE_OK)
588       {
589 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
590 	  goto stop;
591       }
592 
593 /* preparing the QUERY RELATION/WAYS statement */
594     strcpy (sql, "SELECT r.rel_id, r.version, r.timestamp, r.uid, ");
595     strcat (sql, "r.user, r.changeset, w.role, w.ref ");
596     strcat (sql, "FROM osm_relations AS r ");
597     strcat (sql,
598 	    "JOIN osm_relation_refs AS w ON (w.type = 'W' AND w.rel_id = r.rel_id) ");
599     strcat (sql, "WHERE r.rel_id = ? ");
600     strcat (sql, "ORDER BY r.rel_id, w.sub");
601     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &query_way, NULL);
602     if (ret != SQLITE_OK)
603       {
604 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
605 	  goto stop;
606       }
607 
608 /* preparing the QUERY RELATION/RELATIONS statement */
609     strcpy (sql, "SELECT r.rel_id, r.version, r.timestamp, r.uid, ");
610     strcat (sql, "r.user, r.changeset, x.role, x.ref ");
611     strcat (sql, "FROM osm_relations AS r ");
612     strcat (sql,
613 	    "JOIN osm_relation_refs AS x ON (x.type = 'R' AND x.rel_id = r.rel_id) ");
614     strcat (sql, "WHERE r.rel_id = ? ");
615     strcat (sql, "ORDER BY r.rel_id, x.sub");
616     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &query_rel, NULL);
617     if (ret != SQLITE_OK)
618       {
619 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
620 	  goto stop;
621       }
622 
623 /* preparing the QUERY RELATION/TAGS statement */
624     strcpy (sql, "SELECT t.k, t.v ");
625     strcat (sql, "FROM osm_relations AS r ");
626     strcat (sql, "JOIN osm_relation_tags AS t ON (t.rel_id = r.rel_id) ");
627     strcat (sql, "WHERE r.rel_id = ? ");
628     strcat (sql, "ORDER BY r.rel_id, t.sub");
629     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &query_tag, NULL);
630     if (ret != SQLITE_OK)
631       {
632 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
633 	  goto stop;
634       }
635 
636     while (1)
637       {
638 	  /* scrolling the result set */
639 	  ret = sqlite3_step (rel_query);
640 	  if (ret == SQLITE_DONE)
641 	    {
642 		/* there are no more rows to fetch - we can stop looping */
643 		break;
644 	    }
645 	  if (ret == SQLITE_ROW)
646 	    {
647 		/* ok, we've just fetched a valid row */
648 		sqlite3_int64 id = sqlite3_column_int64 (rel_query, 0);
649 
650 		sqlite3_reset (query_way);
651 		sqlite3_clear_bindings (query_way);
652 		sqlite3_bind_int64 (query_way, 1, id);
653 		first = 1;
654 		while (1)
655 		  {
656 		      /* scrolling the result set */
657 		      ret = sqlite3_step (query_way);
658 		      if (ret == SQLITE_DONE)
659 			{
660 			    /* there are no more rows to fetch - we can stop looping */
661 			    break;
662 			}
663 		      if (ret == SQLITE_ROW)
664 			{
665 			    /* ok, we've just fetched a valid row */
666 			    sqlite3_int64 id =
667 				sqlite3_column_int64 (query_way, 0);
668 			    int version = sqlite3_column_int (query_way, 1);
669 			    const char *p_timestamp =
670 				(const char *) sqlite3_column_text (query_way,
671 								    2);
672 			    int uid = sqlite3_column_int (query_way, 3);
673 			    const char *p_user =
674 				(const char *) sqlite3_column_text (query_way,
675 								    4);
676 			    const char *p_changeset =
677 				(const char *) sqlite3_column_text (query_way,
678 								    5);
679 			    char *role =
680 				clean_xml ((const char *)
681 					   sqlite3_column_text (query_way, 6));
682 			    sqlite3_int64 way_id =
683 				sqlite3_column_int64 (query_way, 7);
684 
685 			    if (first)
686 			      {
687 				  /* first RELATION row */
688 				  char *timestamp =
689 				      p_timestamp ? clean_xml (p_timestamp) :
690 				      NULL;
691 				  char *changeset =
692 				      p_changeset ? clean_xml (p_changeset) :
693 				      NULL;
694 				  char *user = NULL;
695 				  if (p_user)
696 				      user = clean_xml (p_user);
697 				  first = 0;
698 #if defined(_WIN32) || defined(__MINGW32__)
699 /* CAVEAT - M$ runtime doesn't supports %lld for 64 bits */
700 				  fprintf (out, "\t<relation id=\"%I64d\"", id);
701 #else
702 				  fprintf (out, "\t<relation id=\"%lld\"", id);
703 #endif
704 				  if (user)
705 				    {
706 					fprintf (out, " user=\"%s\"", user);
707 					free (user);
708 				    }
709 				  if (changeset)
710 				    {
711 					fprintf (out, " changeset=\"%s\"",
712 						 changeset);
713 					free (changeset);
714 				    }
715 				  if (timestamp)
716 				    {
717 					fprintf (out, " timestamp=\"%s\"",
718 						 timestamp);
719 					free (timestamp);
720 				    }
721 				  if (!version)
722 				      version = 1;
723 				  fprintf (out, " version=\"%d\"", version);
724 				  fprintf (out, " uid=\"%d\" >\n", uid);
725 			      }
726 			    /* NODE REF tag */
727 #if defined(_WIN32) || defined(__MINGW32__)
728 /* CAVEAT - M$ runtime doesn't supports %lld for 64 bits */
729 			    fprintf (out,
730 				     "\t\t<member type=\"way\" ref=\"%I64d\" role=\"%s\"/>\n",
731 				     way_id, role);
732 #else
733 			    fprintf (out,
734 				     "\t\t<member type = \"way\" ref=\"%lld\" role=\"%s\"/>\n",
735 				     way_id, role);
736 #endif
737 			    free (role);
738 			}
739 		      else
740 			{
741 			    /* some unexpected error occurred */
742 			    fprintf (stderr, "sqlite3_step() error: %s\n",
743 				     sqlite3_errmsg (handle));
744 			    goto stop;
745 			}
746 		  }
747 		if (!first)
748 		  {
749 		      /* exporting WAY tags */
750 		      sqlite3_reset (query_tag);
751 		      sqlite3_clear_bindings (query_tag);
752 		      sqlite3_bind_int64 (query_tag, 1, id);
753 		      while (1)
754 			{
755 			    /* scrolling the result set */
756 			    ret = sqlite3_step (query_tag);
757 			    if (ret == SQLITE_DONE)
758 			      {
759 				  /* there are no more rows to fetch - we can stop looping */
760 				  break;
761 			      }
762 			    if (ret == SQLITE_ROW)
763 			      {
764 				  /* ok, we've just fetched a valid row */
765 				  char *k =
766 				      clean_xml ((const char *)
767 						 sqlite3_column_text (query_tag,
768 								      0));
769 				  char *v =
770 				      clean_xml ((const char *)
771 						 sqlite3_column_text (query_tag,
772 								      1));
773 				  fprintf (out,
774 					   "\t\t<tag k=\"%s\" v=\"%s\"/>\n", k,
775 					   v);
776 				  free (k);
777 				  free (v);
778 			      }
779 			    else
780 			      {
781 				  /* some unexpected error occurred */
782 				  fprintf (stderr, "sqlite3_step() error: %s\n",
783 					   sqlite3_errmsg (handle));
784 				  goto stop;
785 			      }
786 			}
787 		  }
788 		fprintf (out, "\t</relation>\n");
789 	    }
790 	  else
791 	    {
792 		/* some unexpected error occurred */
793 		fprintf (stderr, "sqlite3_step() error: %s\n",
794 			 sqlite3_errmsg (handle));
795 		goto stop;
796 	    }
797       }
798     sqlite3_finalize (rel_query);
799     sqlite3_finalize (query_nd);
800     sqlite3_finalize (query_way);
801     sqlite3_finalize (query_rel);
802     sqlite3_finalize (query_tag);
803 
804     return 1;
805 
806   stop:
807     sqlite3_finalize (rel_query);
808     if (query_nd)
809 	sqlite3_finalize (query_nd);
810     if (query_way)
811 	sqlite3_finalize (query_way);
812     if (query_rel)
813 	sqlite3_finalize (query_rel);
814     if (query_tag)
815 	sqlite3_finalize (query_tag);
816     return 0;
817 }
818 
819 static int
reset_filtered(sqlite3 * handle)820 reset_filtered (sqlite3 * handle)
821 {
822 /* resetting NODES, WAYS and RELATIONS */
823     char sql[1024];
824     int ret;
825     char *sql_err = NULL;
826 
827 /* disabling transactions */
828     strcpy (sql, "PRAGMA journal_mode=OFF");
829     ret = sqlite3_exec (handle, sql, NULL, NULL, &sql_err);
830     if (ret != SQLITE_OK)
831       {
832 	  fprintf (stderr, "PRAGMA journal_mode=OFF: %s\n", sql_err);
833 	  sqlite3_free (sql_err);
834 	  return 0;
835       }
836 
837 /* resetting NODES */
838     strcpy (sql, "UPDATE osm_nodes SET filtered = 0");
839     ret = sqlite3_exec (handle, sql, NULL, NULL, &sql_err);
840     if (ret != SQLITE_OK)
841       {
842 	  fprintf (stderr, "RESET osm_nodes error: %s\n", sql_err);
843 	  sqlite3_free (sql_err);
844 	  return 0;
845       }
846 
847 /* resetting WAYS */
848     strcpy (sql, "UPDATE osm_ways SET filtered = 0");
849     ret = sqlite3_exec (handle, sql, NULL, NULL, &sql_err);
850     if (ret != SQLITE_OK)
851       {
852 	  fprintf (stderr, "RESET osm_ways error: %s\n", sql_err);
853 	  sqlite3_free (sql_err);
854 	  return 0;
855       }
856 
857 /* resetting RELATIONS */
858     strcpy (sql, "UPDATE osm_relations SET filtered = 0");
859     ret = sqlite3_exec (handle, sql, NULL, NULL, &sql_err);
860     if (ret != SQLITE_OK)
861       {
862 	  fprintf (stderr, "RESET osm_relations error: %s\n", sql_err);
863 	  sqlite3_free (sql_err);
864 	  return 0;
865       }
866 
867 /* enabling again transactions */
868     strcpy (sql, "PRAGMA journal_mode=DELETE");
869     ret = sqlite3_exec (handle, sql, NULL, NULL, &sql_err);
870     if (ret != SQLITE_OK)
871       {
872 	  fprintf (stderr, "PRAGMA journal_mode=DELETE: %s\n", sql_err);
873 	  sqlite3_free (sql_err);
874 	  return 0;
875       }
876 
877     return 1;
878 }
879 
880 static int
filter_rel_relations(sqlite3 * handle)881 filter_rel_relations (sqlite3 * handle)
882 {
883 /* selecting any RELATION required by other selected RELATIONS */
884     char sql[1024];
885     int ret;
886     char *sql_err = NULL;
887 
888     strcpy (sql, "UPDATE osm_relations SET filtered = 1 ");
889     strcat (sql, "WHERE rel_id IN (");
890     strcat (sql, "SELECT x.ref ");
891     strcat (sql, "FROM osm_relations AS r ");
892     strcat (sql,
893 	    "JOIN osm_relation_refs AS x ON (x.type = 'R' AND r.rel_id = x.rel_id) ");
894     strcat (sql, "WHERE r.filtered = 1)");
895     ret = sqlite3_exec (handle, sql, NULL, NULL, &sql_err);
896     if (ret != SQLITE_OK)
897       {
898 	  fprintf (stderr, "UPDATE osm_relations error: %s\n", sql_err);
899 	  sqlite3_free (sql_err);
900 	  return 0;
901       }
902     return 1;
903 }
904 
905 static int
filter_way_relations(sqlite3 * handle)906 filter_way_relations (sqlite3 * handle)
907 {
908 /* selecting any WAY required by selected RELATIONS */
909     char sql[1024];
910     int ret;
911     char *sql_err = NULL;
912 
913     strcpy (sql, "UPDATE osm_ways SET filtered = 1 ");
914     strcat (sql, "WHERE way_id IN ( ");
915     strcat (sql, "SELECT w.ref ");
916     strcat (sql, "FROM osm_relations AS r ");
917     strcat (sql,
918 	    "JOIN osm_relation_refs AS w ON (w.type = 'W' AND r.rel_id = w.rel_id) ");
919     strcat (sql, "WHERE r.filtered = 1)");
920     ret = sqlite3_exec (handle, sql, NULL, NULL, &sql_err);
921     if (ret != SQLITE_OK)
922       {
923 	  fprintf (stderr, "UPDATE osm_ways error: %s\n", sql_err);
924 	  sqlite3_free (sql_err);
925 	  return 0;
926       }
927     return 1;
928 }
929 
930 static int
filter_node_relations(sqlite3 * handle)931 filter_node_relations (sqlite3 * handle)
932 {
933 /* selecting any NODE required by selected RELATIONS */
934     char sql[1024];
935     int ret;
936     char *sql_err = NULL;
937 
938     strcpy (sql, "UPDATE osm_nodes SET filtered = 1 ");
939     strcat (sql, "WHERE node_id IN ( ");
940     strcat (sql, "SELECT n.ref ");
941     strcat (sql, "FROM osm_relations AS r ");
942     strcat (sql,
943 	    "JOIN osm_relation_refs AS n ON (n.type = 'N' AND r.rel_id = n.rel_id) ");
944     strcat (sql, "WHERE r.filtered = 1)");
945     ret = sqlite3_exec (handle, sql, NULL, NULL, &sql_err);
946     if (ret != SQLITE_OK)
947       {
948 	  fprintf (stderr, "UPDATE osm_nodes error: %s\n", sql_err);
949 	  sqlite3_free (sql_err);
950 	  return 0;
951       }
952     return 1;
953 }
954 
955 static int
filter_node_ways(sqlite3 * handle)956 filter_node_ways (sqlite3 * handle)
957 {
958 /* selecting any NODE required by selected WAYS */
959     char sql[1024];
960     int ret;
961     char *sql_err = NULL;
962 
963     strcpy (sql, "UPDATE osm_nodes SET filtered = 1 ");
964     strcat (sql, "WHERE node_id IN ( SELECT n.node_id ");
965     strcat (sql, "FROM osm_ways AS w ");
966     strcat (sql, "JOIN osm_way_refs AS n ON (w.way_id = n.way_id) ");
967     strcat (sql, "WHERE w.filtered = 1)");
968     ret = sqlite3_exec (handle, sql, NULL, NULL, &sql_err);
969     if (ret != SQLITE_OK)
970       {
971 	  fprintf (stderr, "UPDATE osm_nodes error: %s\n", sql_err);
972 	  sqlite3_free (sql_err);
973 	  return 0;
974       }
975     return 1;
976 }
977 
978 static int
filter_nodes(sqlite3 * handle,void * mask,int mask_len)979 filter_nodes (sqlite3 * handle, void *mask, int mask_len)
980 {
981 /* filtering any NODE to be exported */
982     char sql[1024];
983     int ret;
984     sqlite3_stmt *query = NULL;
985     sqlite3_stmt *stmt_nodes = NULL;
986     sqlite3_stmt *stmt_ways = NULL;
987     sqlite3_stmt *stmt_rels = NULL;
988     char *sql_err = NULL;
989 
990 /* the complete INSERT operation is handled as an unique SQL Transaction */
991     ret = sqlite3_exec (handle, "BEGIN", NULL, NULL, &sql_err);
992     if (ret != SQLITE_OK)
993       {
994 	  fprintf (stderr, "BEGIN TRANSACTION error: %s\n", sql_err);
995 	  sqlite3_free (sql_err);
996 	  return 0;
997       }
998 
999 /* preparing the UPDATE NODES statement */
1000     strcpy (sql, "UPDATE osm_nodes SET filtered = 1 WHERE node_id = ?");
1001     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt_nodes, NULL);
1002     if (ret != SQLITE_OK)
1003       {
1004 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
1005 	  return 0;
1006       }
1007 
1008 /* preparing the UPDATE WAYS statement */
1009     strcpy (sql, "UPDATE osm_ways SET filtered = 1 WHERE way_id IN (");
1010     strcat (sql, "SELECT way_id FROM osm_way_refs WHERE node_id = ?)");
1011     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt_ways, NULL);
1012     if (ret != SQLITE_OK)
1013       {
1014 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
1015 	  return 0;
1016       }
1017 
1018 /* preparing the UPDATE RELATIONS statement */
1019     strcpy (sql, "UPDATE osm_relations SET filtered = 1 WHERE rel_id IN (");
1020     strcat (sql,
1021 	    "SELECT rel_id FROM osm_relation_refs WHERE type = 'N' AND ref = ?)");
1022     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt_rels, NULL);
1023     if (ret != SQLITE_OK)
1024       {
1025 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
1026 	  return 0;
1027       }
1028 
1029 /* preparing the QUERY NODES statement */
1030     strcpy (sql, "SELECT node_id FROM osm_nodes ");
1031     strcat (sql, "WHERE MbrIntersects(Geometry, ?) = 1 ");
1032     strcat (sql, "AND ST_Intersects(Geometry, ?) = 1");
1033     ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &query, NULL);
1034     if (ret != SQLITE_OK)
1035       {
1036 	  fprintf (stderr, "SQL error: %s\n%s\n", sql, sqlite3_errmsg (handle));
1037 	  return 0;
1038       }
1039     sqlite3_bind_blob (query, 1, mask, mask_len, SQLITE_STATIC);
1040     sqlite3_bind_blob (query, 2, mask, mask_len, SQLITE_STATIC);
1041 
1042     while (1)
1043       {
1044 	  /* scrolling the result set */
1045 	  ret = sqlite3_step (query);
1046 	  if (ret == SQLITE_DONE)
1047 	    {
1048 		/* there are no more rows to fetch - we can stop looping */
1049 		break;
1050 	    }
1051 	  if (ret == SQLITE_ROW)
1052 	    {
1053 		/* ok, we've just fetched a valid row */
1054 		sqlite3_int64 id = sqlite3_column_int64 (query, 0);
1055 
1056 		/* marking this NODE as filtered */
1057 		sqlite3_reset (stmt_nodes);
1058 		sqlite3_clear_bindings (stmt_nodes);
1059 		sqlite3_bind_int64 (stmt_nodes, 1, id);
1060 		ret = sqlite3_step (stmt_nodes);
1061 		if (ret == SQLITE_DONE || ret == SQLITE_ROW)
1062 		    ;
1063 		else
1064 		  {
1065 		      fprintf (stderr, "sqlite3_step() error: UPDATE NODES\n");
1066 		      goto stop;
1067 		  }
1068 
1069 		/* marking any dependent WAY as filtered */
1070 		sqlite3_reset (stmt_ways);
1071 		sqlite3_clear_bindings (stmt_ways);
1072 		sqlite3_bind_int64 (stmt_ways, 1, id);
1073 		ret = sqlite3_step (stmt_ways);
1074 		if (ret == SQLITE_DONE || ret == SQLITE_ROW)
1075 		    ;
1076 		else
1077 		  {
1078 		      fprintf (stderr, "sqlite3_step() error: UPDATE WAYS\n");
1079 		      goto stop;
1080 		  }
1081 
1082 		/* marking any dependent RELATION as filtered */
1083 		sqlite3_reset (stmt_rels);
1084 		sqlite3_clear_bindings (stmt_rels);
1085 		sqlite3_bind_int64 (stmt_rels, 1, id);
1086 		ret = sqlite3_step (stmt_rels);
1087 		if (ret == SQLITE_DONE || ret == SQLITE_ROW)
1088 		    ;
1089 		else
1090 		  {
1091 		      fprintf (stderr,
1092 			       "sqlite3_step() error: UPDATE RELATIONS\n");
1093 		      goto stop;
1094 		  }
1095 	    }
1096 	  else
1097 	    {
1098 		/* some unexpected error occurred */
1099 		fprintf (stderr, "sqlite3_step() error: %s\n",
1100 			 sqlite3_errmsg (handle));
1101 		goto stop;
1102 	    }
1103       }
1104     sqlite3_finalize (query);
1105     sqlite3_finalize (stmt_nodes);
1106     sqlite3_finalize (stmt_ways);
1107     sqlite3_finalize (stmt_rels);
1108 
1109 /* committing the still pending SQL Transaction */
1110     ret = sqlite3_exec (handle, "COMMIT", NULL, NULL, &sql_err);
1111     if (ret != SQLITE_OK)
1112       {
1113 	  fprintf (stderr, "COMMIT TRANSACTION error: %s\n", sql_err);
1114 	  sqlite3_free (sql_err);
1115 	  return 0;
1116       }
1117     return 1;
1118 
1119   stop:
1120     if (query)
1121 	sqlite3_finalize (query);
1122     if (stmt_nodes)
1123 	sqlite3_finalize (stmt_nodes);
1124     if (stmt_ways)
1125 	sqlite3_finalize (stmt_ways);
1126     if (stmt_rels)
1127 	sqlite3_finalize (stmt_rels);
1128     return 0;
1129 }
1130 
1131 static int
parse_wkt_mask(const char * wkt_path,void ** mask,int * mask_len)1132 parse_wkt_mask (const char *wkt_path, void **mask, int *mask_len)
1133 {
1134 /* acquiring the WKT mask */
1135     int cnt = 0;
1136     char *wkt_buf = NULL;
1137     char *p;
1138     int c;
1139     gaiaGeomCollPtr geom = NULL;
1140 
1141 /* opening the text file containing the WKT mask */
1142     FILE *in = fopen (wkt_path, "r");
1143     if (in == NULL)
1144       {
1145 	  fprintf (stderr, "Unable to open: %s\n", wkt_path);
1146 	  return 0;
1147       }
1148 
1149 /* counting how many chars are there */
1150     while (getc (in) != EOF)
1151 	cnt++;
1152     if (cnt == 0)
1153       {
1154 	  fprintf (stderr, "Empty file: %s\n", wkt_path);
1155 	  fclose (in);
1156 	  return 0;
1157       }
1158 
1159 /* allocating the WKT buffer */
1160     wkt_buf = malloc (cnt + 1);
1161     memset (wkt_buf, '\0', cnt + 1);
1162     p = wkt_buf;
1163 /* restarting the text file */
1164     rewind (in);
1165 
1166     while ((c = getc (in)) != EOF)
1167       {
1168 	  /* loading the WKT buffer */
1169 	  if ((p - wkt_buf) <= cnt)
1170 	      *p++ = c;
1171       }
1172     *p = '\0';
1173     fclose (in);
1174 
1175 /* attempting to parse the WKT expression */
1176     geom = gaiaParseWkt ((unsigned char *) wkt_buf, -1);
1177     free (wkt_buf);
1178     if (!geom)
1179 	return 0;
1180 
1181 /* converting to Binary Blob */
1182     gaiaToSpatiaLiteBlobWkb (geom, (unsigned char **) mask, mask_len);
1183     gaiaFreeGeomColl (geom);
1184     return 1;
1185 }
1186 
1187 static void
open_db(const char * path,sqlite3 ** handle,int cache_size,void * cache)1188 open_db (const char *path, sqlite3 ** handle, int cache_size, void *cache)
1189 {
1190 /* opening the DB */
1191     sqlite3 *db_handle;
1192     int ret;
1193     char sql[1024];
1194     int spatialite_rs = 0;
1195     int spatialite_gc = 0;
1196     int rs_srid = 0;
1197     int auth_name = 0;
1198     int auth_srid = 0;
1199     int ref_sys_name = 0;
1200     int proj4text = 0;
1201     int f_table_name = 0;
1202     int f_geometry_column = 0;
1203     int coord_dimension = 0;
1204     int gc_srid = 0;
1205     int type = 0;
1206     int geometry_type = 0;
1207     int spatial_index_enabled = 0;
1208     int node_id = 0;
1209     int version = 0;
1210     int timestamp = 0;
1211     int uid = 0;
1212     int user = 0;
1213     int changeset = 0;
1214     int filtered = 0;
1215     int geometry = 0;
1216     int sub = 0;
1217     int k = 0;
1218     int v = 0;
1219     int way_id = 0;
1220     int rel_id = 0;
1221     int role = 0;
1222     int ref = 0;
1223     const char *name;
1224     int i;
1225     char **results;
1226     int rows;
1227     int columns;
1228 
1229     *handle = NULL;
1230     printf ("SQLite version: %s\n", sqlite3_libversion ());
1231     printf ("SpatiaLite version: %s\n\n", spatialite_version ());
1232 
1233     ret = sqlite3_open_v2 (path, &db_handle, SQLITE_OPEN_READWRITE, NULL);
1234     if (ret != SQLITE_OK)
1235       {
1236 	  fprintf (stderr, "cannot open '%s': %s\n", path,
1237 		   sqlite3_errmsg (db_handle));
1238 	  sqlite3_close (db_handle);
1239 	  return;
1240       }
1241     spatialite_init_ex (db_handle, cache, 0);
1242     if (cache_size > 0)
1243       {
1244 	  /* setting the CACHE-SIZE */
1245 	  sprintf (sql, "PRAGMA cache_size=%d", cache_size);
1246 	  sqlite3_exec (db_handle, sql, NULL, NULL, NULL);
1247       }
1248 
1249 /* checking the GEOMETRY_COLUMNS table */
1250     strcpy (sql, "PRAGMA table_info(geometry_columns)");
1251     ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
1252     if (ret != SQLITE_OK)
1253 	goto unknown;
1254     if (rows < 1)
1255 	;
1256     else
1257       {
1258 	  for (i = 1; i <= rows; i++)
1259 	    {
1260 		name = results[(i * columns) + 1];
1261 		if (strcasecmp (name, "f_table_name") == 0)
1262 		    f_table_name = 1;
1263 		if (strcasecmp (name, "f_geometry_column") == 0)
1264 		    f_geometry_column = 1;
1265 		if (strcasecmp (name, "coord_dimension") == 0)
1266 		    coord_dimension = 1;
1267 		if (strcasecmp (name, "srid") == 0)
1268 		    gc_srid = 1;
1269 		if (strcasecmp (name, "type") == 0)
1270 		    type = 1;
1271 		if (strcasecmp (name, "geometry_type") == 0)
1272 		    geometry_type = 1;
1273 		if (strcasecmp (name, "spatial_index_enabled") == 0)
1274 		    spatial_index_enabled = 1;
1275 	    }
1276       }
1277     sqlite3_free_table (results);
1278     if (f_table_name && f_geometry_column && type && coord_dimension
1279 	&& gc_srid && spatial_index_enabled)
1280 	spatialite_gc = 1;
1281     if (f_table_name && f_geometry_column && geometry_type && coord_dimension
1282 	&& gc_srid && spatial_index_enabled)
1283 	spatialite_gc = 3;
1284 
1285 /* checking the SPATIAL_REF_SYS table */
1286     strcpy (sql, "PRAGMA table_info(spatial_ref_sys)");
1287     ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
1288     if (ret != SQLITE_OK)
1289 	goto unknown;
1290     if (rows < 1)
1291 	;
1292     else
1293       {
1294 	  for (i = 1; i <= rows; i++)
1295 	    {
1296 		name = results[(i * columns) + 1];
1297 		if (strcasecmp (name, "srid") == 0)
1298 		    rs_srid = 1;
1299 		if (strcasecmp (name, "auth_name") == 0)
1300 		    auth_name = 1;
1301 		if (strcasecmp (name, "auth_srid") == 0)
1302 		    auth_srid = 1;
1303 		if (strcasecmp (name, "ref_sys_name") == 0)
1304 		    ref_sys_name = 1;
1305 		if (strcasecmp (name, "proj4text") == 0)
1306 		    proj4text = 1;
1307 	    }
1308       }
1309     sqlite3_free_table (results);
1310     if (rs_srid && auth_name && auth_srid && ref_sys_name && proj4text)
1311 	spatialite_rs = 1;
1312 /* verifying the MetaData format */
1313     if (spatialite_gc && spatialite_rs)
1314 	;
1315     else
1316 	goto unknown;
1317 
1318 /* checking the OSM_NODES table */
1319     strcpy (sql, "PRAGMA table_info(osm_nodes)");
1320     ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
1321     if (ret != SQLITE_OK)
1322 	goto unknown;
1323     if (rows < 1)
1324 	;
1325     else
1326       {
1327 	  for (i = 1; i <= rows; i++)
1328 	    {
1329 		name = results[(i * columns) + 1];
1330 		if (strcasecmp (name, "node_id") == 0)
1331 		    node_id = 1;
1332 		if (strcasecmp (name, "version") == 0)
1333 		    version = 1;
1334 		if (strcasecmp (name, "timestamp") == 0)
1335 		    timestamp = 1;
1336 		if (strcasecmp (name, "uid") == 0)
1337 		    uid = 1;
1338 		if (strcasecmp (name, "user") == 0)
1339 		    user = 1;
1340 		if (strcasecmp (name, "changeset") == 0)
1341 		    changeset = 1;
1342 		if (strcasecmp (name, "filtered") == 0)
1343 		    filtered = 1;
1344 		if (strcasecmp (name, "Geometry") == 0)
1345 		    geometry = 1;
1346 	    }
1347       }
1348     sqlite3_free_table (results);
1349     if (node_id && version && timestamp && uid && user && changeset && filtered
1350 	&& geometry)
1351 	;
1352     else
1353 	goto unknown;
1354 
1355 /* checking the OSM_NODE_TAGS table */
1356     strcpy (sql, "PRAGMA table_info(osm_node_tags)");
1357     ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
1358     if (ret != SQLITE_OK)
1359 	goto unknown;
1360     if (rows < 1)
1361 	;
1362     else
1363       {
1364 	  node_id = 0;
1365 	  for (i = 1; i <= rows; i++)
1366 	    {
1367 		name = results[(i * columns) + 1];
1368 		if (strcasecmp (name, "node_id") == 0)
1369 		    node_id = 1;
1370 		if (strcasecmp (name, "sub") == 0)
1371 		    sub = 1;
1372 		if (strcasecmp (name, "k") == 0)
1373 		    k = 1;
1374 		if (strcasecmp (name, "v") == 0)
1375 		    v = 1;
1376 	    }
1377       }
1378     sqlite3_free_table (results);
1379     if (node_id && sub && k && v)
1380 	;
1381     else
1382 	goto unknown;
1383 
1384 /* checking the OSM_WAYS table */
1385     strcpy (sql, "PRAGMA table_info(osm_ways)");
1386     ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
1387     if (ret != SQLITE_OK)
1388 	goto unknown;
1389     if (rows < 1)
1390 	;
1391     else
1392       {
1393 	  version = 0;
1394 	  timestamp = 0;
1395 	  uid = 0;
1396 	  user = 0;
1397 	  changeset = 0;
1398 	  filtered = 0;
1399 	  for (i = 1; i <= rows; i++)
1400 	    {
1401 		name = results[(i * columns) + 1];
1402 		if (strcasecmp (name, "way_id") == 0)
1403 		    way_id = 1;
1404 		if (strcasecmp (name, "version") == 0)
1405 		    version = 1;
1406 		if (strcasecmp (name, "timestamp") == 0)
1407 		    timestamp = 1;
1408 		if (strcasecmp (name, "uid") == 0)
1409 		    uid = 1;
1410 		if (strcasecmp (name, "user") == 0)
1411 		    user = 1;
1412 		if (strcasecmp (name, "changeset") == 0)
1413 		    changeset = 1;
1414 		if (strcasecmp (name, "filtered") == 0)
1415 		    filtered = 1;
1416 	    }
1417       }
1418     sqlite3_free_table (results);
1419     if (way_id && version && timestamp && uid && user && changeset && filtered)
1420 	;
1421     else
1422 	goto unknown;
1423 
1424 /* checking the OSM_WAY_TAGS table */
1425     strcpy (sql, "PRAGMA table_info(osm_way_tags)");
1426     ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
1427     if (ret != SQLITE_OK)
1428 	goto unknown;
1429     if (rows < 1)
1430 	;
1431     else
1432       {
1433 	  way_id = 0;
1434 	  sub = 0;
1435 	  k = 0;
1436 	  v = 0;
1437 	  for (i = 1; i <= rows; i++)
1438 	    {
1439 		name = results[(i * columns) + 1];
1440 		if (strcasecmp (name, "way_id") == 0)
1441 		    way_id = 1;
1442 		if (strcasecmp (name, "sub") == 0)
1443 		    sub = 1;
1444 		if (strcasecmp (name, "k") == 0)
1445 		    k = 1;
1446 		if (strcasecmp (name, "v") == 0)
1447 		    v = 1;
1448 	    }
1449       }
1450     sqlite3_free_table (results);
1451     if (way_id && sub && k && v)
1452 	;
1453     else
1454 	goto unknown;
1455 
1456 /* checking the OSM_WAY_REFS table */
1457     strcpy (sql, "PRAGMA table_info(osm_way_refs)");
1458     ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
1459     if (ret != SQLITE_OK)
1460 	goto unknown;
1461     if (rows < 1)
1462 	;
1463     else
1464       {
1465 	  way_id = 0;
1466 	  sub = 0;
1467 	  node_id = 0;
1468 	  for (i = 1; i <= rows; i++)
1469 	    {
1470 		name = results[(i * columns) + 1];
1471 		if (strcasecmp (name, "way_id") == 0)
1472 		    way_id = 1;
1473 		if (strcasecmp (name, "sub") == 0)
1474 		    sub = 1;
1475 		if (strcasecmp (name, "node_id") == 0)
1476 		    node_id = 1;
1477 	    }
1478       }
1479     sqlite3_free_table (results);
1480     if (way_id && sub && node_id)
1481 	;
1482     else
1483 	goto unknown;
1484 
1485 /* checking the OSM_RELATIONS table */
1486     strcpy (sql, "PRAGMA table_info(osm_relations)");
1487     ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
1488     if (ret != SQLITE_OK)
1489 	goto unknown;
1490     if (rows < 1)
1491 	;
1492     else
1493       {
1494 	  version = 0;
1495 	  timestamp = 0;
1496 	  uid = 0;
1497 	  user = 0;
1498 	  changeset = 0;
1499 	  filtered = 0;
1500 	  for (i = 1; i <= rows; i++)
1501 	    {
1502 		name = results[(i * columns) + 1];
1503 		if (strcasecmp (name, "rel_id") == 0)
1504 		    rel_id = 1;
1505 		if (strcasecmp (name, "version") == 0)
1506 		    version = 1;
1507 		if (strcasecmp (name, "timestamp") == 0)
1508 		    timestamp = 1;
1509 		if (strcasecmp (name, "uid") == 0)
1510 		    uid = 1;
1511 		if (strcasecmp (name, "user") == 0)
1512 		    user = 1;
1513 		if (strcasecmp (name, "changeset") == 0)
1514 		    changeset = 1;
1515 		if (strcasecmp (name, "filtered") == 0)
1516 		    filtered = 1;
1517 	    }
1518       }
1519     sqlite3_free_table (results);
1520     if (rel_id && version && timestamp && uid && user && changeset && filtered)
1521 	;
1522     else
1523 	goto unknown;
1524 
1525 /* checking the OSM_RELATION_TAGS table */
1526     strcpy (sql, "PRAGMA table_info(osm_relation_tags)");
1527     ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
1528     if (ret != SQLITE_OK)
1529 	goto unknown;
1530     if (rows < 1)
1531 	;
1532     else
1533       {
1534 	  rel_id = 0;
1535 	  sub = 0;
1536 	  k = 0;
1537 	  v = 0;
1538 	  for (i = 1; i <= rows; i++)
1539 	    {
1540 		name = results[(i * columns) + 1];
1541 		if (strcasecmp (name, "rel_id") == 0)
1542 		    rel_id = 1;
1543 		if (strcasecmp (name, "sub") == 0)
1544 		    sub = 1;
1545 		if (strcasecmp (name, "k") == 0)
1546 		    k = 1;
1547 		if (strcasecmp (name, "v") == 0)
1548 		    v = 1;
1549 	    }
1550       }
1551     sqlite3_free_table (results);
1552     if (rel_id && sub && k && v)
1553 	;
1554     else
1555 	goto unknown;
1556 
1557 /* checking the OSM_RELATION_REFS table */
1558     strcpy (sql, "PRAGMA table_info(osm_relation_refs)");
1559     ret = sqlite3_get_table (db_handle, sql, &results, &rows, &columns, NULL);
1560     if (ret != SQLITE_OK)
1561 	goto unknown;
1562     if (rows < 1)
1563 	;
1564     else
1565       {
1566 	  rel_id = 0;
1567 	  sub = 0;
1568 	  type = 0;
1569 	  for (i = 1; i <= rows; i++)
1570 	    {
1571 		name = results[(i * columns) + 1];
1572 		if (strcasecmp (name, "rel_id") == 0)
1573 		    rel_id = 1;
1574 		if (strcasecmp (name, "sub") == 0)
1575 		    sub = 1;
1576 		if (strcasecmp (name, "type") == 0)
1577 		    type = 1;
1578 		if (strcasecmp (name, "ref") == 0)
1579 		    ref = 1;
1580 		if (strcasecmp (name, "role") == 0)
1581 		    role = 1;
1582 	    }
1583       }
1584     sqlite3_free_table (results);
1585     if (rel_id && sub && type && ref && role)
1586 	;
1587     else
1588 	goto unknown;
1589 
1590     *handle = db_handle;
1591     return;
1592 
1593   unknown:
1594     if (db_handle)
1595 	sqlite3_close (db_handle);
1596     fprintf (stderr, "DB '%s'\n", path);
1597     fprintf (stderr, "doesn't seems to contain valid OSM-RAW data ...\n\n");
1598     return;
1599 }
1600 
1601 static void
do_version()1602 do_version ()
1603 {
1604 /* printing version infos */
1605 	fprintf( stderr, "\nVersion infos\n");
1606 	fprintf( stderr, "===========================================\n");
1607     fprintf (stderr, "spatialite_osm_filter: %s\n", SPATIALITE_VERSION);
1608 	fprintf (stderr, "target CPU ..........: %s\n", spatialite_target_cpu ());
1609     fprintf (stderr, "libspatialite .......: %s\n", spatialite_version ());
1610     fprintf (stderr, "libsqlite3 ..........: %s\n", sqlite3_libversion ());
1611     fprintf (stderr, "\n");
1612 }
1613 
1614 static void
do_help()1615 do_help ()
1616 {
1617 /* printing the argument list */
1618     fprintf (stderr, "\n\nusage: spatialite_osm_filter ARGLIST\n");
1619     fprintf (stderr,
1620 	     "==============================================================\n");
1621     fprintf (stderr,
1622 	     "-h or --help                    print this help message\n");
1623     fprintf (stderr, "-v or --version                 print version infos\n");
1624     fprintf (stderr,
1625 	     "-o or --osm-path pathname       the OSM-XML [output] file path\n");
1626     fprintf (stderr,
1627 	     "-w or --wkt-mask-path pathname  path of text file [WKT mask]\n");
1628     fprintf (stderr,
1629 	     "-d or --db-path  pathname       the SpatiaLite DB path\n\n");
1630     fprintf (stderr, "you can specify the following options as well\n");
1631     fprintf (stderr,
1632 	     "-cs or --cache-size    num      DB cache size (how many pages)\n");
1633     fprintf (stderr,
1634 	     "-m or --in-memory               using IN-MEMORY database\n");
1635     fprintf (stderr,
1636 	     "-jo or --journal-off            unsafe [but faster] mode\n");
1637 }
1638 
1639 int
main(int argc,char * argv[])1640 main (int argc, char *argv[])
1641 {
1642 /* the MAIN function simply perform arguments checking */
1643     sqlite3 *handle;
1644     int i;
1645     int next_arg = ARG_NONE;
1646     const char *osm_path = NULL;
1647     const char *wkt_path = NULL;
1648     const char *db_path = NULL;
1649     int in_memory = 0;
1650     int cache_size = 0;
1651     int journal_off = 0;
1652     int error = 0;
1653     void *mask = NULL;
1654     int mask_len = 0;
1655     FILE *out = NULL;
1656     char *sql_err = NULL;
1657     int ret;
1658     void *cache;
1659 
1660     for (i = 1; i < argc; i++)
1661       {
1662 	  /* parsing the invocation arguments */
1663 	  if (next_arg != ARG_NONE)
1664 	    {
1665 		switch (next_arg)
1666 		  {
1667 		  case ARG_OSM_PATH:
1668 		      osm_path = argv[i];
1669 		      break;
1670 		  case ARG_MASK_PATH:
1671 		      wkt_path = argv[i];
1672 		      break;
1673 		  case ARG_DB_PATH:
1674 		      db_path = argv[i];
1675 		      break;
1676 		  case ARG_CACHE_SIZE:
1677 		      cache_size = atoi (argv[i]);
1678 		      break;
1679 		  };
1680 		next_arg = ARG_NONE;
1681 		continue;
1682 	    }
1683 	  if (strcasecmp (argv[i], "--help") == 0
1684 	      || strcmp (argv[i], "-h") == 0)
1685 	    {
1686 		do_help ();
1687 		return -1;
1688 	    }
1689 	  if (strcasecmp (argv[i], "--version") == 0
1690 	      || strcmp (argv[i], "-v") == 0)
1691 	    {
1692 		do_version ();
1693 		return -1;
1694 	    }
1695 	  if (strcmp (argv[i], "-o") == 0)
1696 	    {
1697 		next_arg = ARG_OSM_PATH;
1698 		continue;
1699 	    }
1700 	  if (strcasecmp (argv[i], "--osm-path") == 0)
1701 	    {
1702 		next_arg = ARG_OSM_PATH;
1703 		continue;
1704 	    }
1705 	  if (strcmp (argv[i], "-w") == 0)
1706 	    {
1707 		next_arg = ARG_MASK_PATH;
1708 		continue;
1709 	    }
1710 	  if (strcasecmp (argv[i], "--wkt-mask-path") == 0)
1711 	    {
1712 		next_arg = ARG_MASK_PATH;
1713 		continue;
1714 	    }
1715 	  if (strcmp (argv[i], "-d") == 0)
1716 	    {
1717 		next_arg = ARG_DB_PATH;
1718 		continue;
1719 	    }
1720 	  if (strcasecmp (argv[i], "--db-path") == 0)
1721 	    {
1722 		next_arg = ARG_DB_PATH;
1723 		continue;
1724 	    }
1725 	  if (strcasecmp (argv[i], "--cache-size") == 0
1726 	      || strcmp (argv[i], "-cs") == 0)
1727 	    {
1728 		next_arg = ARG_CACHE_SIZE;
1729 		continue;
1730 	    }
1731 	  if (strcasecmp (argv[i], "-m") == 0)
1732 	    {
1733 		in_memory = 1;
1734 		next_arg = ARG_NONE;
1735 		continue;
1736 	    }
1737 	  if (strcasecmp (argv[i], "--in-memory") == 0)
1738 	    {
1739 		in_memory = 1;
1740 		next_arg = ARG_NONE;
1741 		continue;
1742 	    }
1743 	  if (strcasecmp (argv[i], "-jo") == 0)
1744 	    {
1745 		journal_off = 1;
1746 		next_arg = ARG_NONE;
1747 		continue;
1748 	    }
1749 	  if (strcasecmp (argv[i], "--journal-off") == 0)
1750 	    {
1751 		journal_off = 1;
1752 		next_arg = ARG_NONE;
1753 		continue;
1754 	    }
1755 	  fprintf (stderr, "unknown argument: %s\n", argv[i]);
1756 	  error = 1;
1757       }
1758     if (error)
1759       {
1760 	  do_help ();
1761 	  return -1;
1762       }
1763 
1764 /* checking the arguments */
1765     if (!osm_path)
1766       {
1767 	  fprintf (stderr,
1768 		   "did you forget setting the --osm-path argument ?\n");
1769 	  error = 1;
1770       }
1771     if (!db_path)
1772       {
1773 	  fprintf (stderr, "did you forget setting the --db-path argument ?\n");
1774 	  error = 1;
1775       }
1776     if (!wkt_path)
1777       {
1778 	  fprintf (stderr,
1779 		   "did you forget setting the --wkt-mask-path argument ?\n");
1780 	  error = 1;
1781       }
1782 
1783     if (error)
1784       {
1785 	  do_help ();
1786 	  return -1;
1787       }
1788 
1789     if (!parse_wkt_mask (wkt_path, &mask, &mask_len))
1790       {
1791 	  fprintf (stderr,
1792 		   "ERROR: Invalid WKT mask [not a valid WKT expression]\n");
1793 	  return -1;
1794       }
1795 
1796 /* opening the DB */
1797     if (in_memory)
1798 	cache_size = 0;
1799     cache = spatialite_alloc_connection ();
1800     open_db (db_path, &handle, cache_size, cache);
1801     if (!handle)
1802 	return -1;
1803     if (in_memory)
1804       {
1805 	  /* loading the DB in-memory */
1806 	  sqlite3 *mem_db_handle;
1807 	  sqlite3_backup *backup;
1808 	  ret =
1809 	      sqlite3_open_v2 (":memory:", &mem_db_handle,
1810 			       SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
1811 			       NULL);
1812 	  if (ret != SQLITE_OK)
1813 	    {
1814 		fprintf (stderr, "cannot open 'MEMORY-DB': %s\n",
1815 			 sqlite3_errmsg (mem_db_handle));
1816 		sqlite3_close (mem_db_handle);
1817 		return -1;
1818 	    }
1819 	  backup = sqlite3_backup_init (mem_db_handle, "main", handle, "main");
1820 	  if (!backup)
1821 	    {
1822 		fprintf (stderr, "cannot load 'MEMORY-DB'\n");
1823 		sqlite3_close (handle);
1824 		sqlite3_close (mem_db_handle);
1825 		return -1;
1826 	    }
1827 	  while (1)
1828 	    {
1829 		ret = sqlite3_backup_step (backup, 1024);
1830 		if (ret == SQLITE_DONE)
1831 		    break;
1832 	    }
1833 	  ret = sqlite3_backup_finish (backup);
1834 	  sqlite3_close (handle);
1835 	  handle = mem_db_handle;
1836 	  printf ("\nusing IN-MEMORY database\n");
1837 	  spatialite_cleanup_ex (cache);
1838 	  cache = spatialite_alloc_connection ();
1839 	  spatialite_init_ex (handle, cache, 0);
1840       }
1841 
1842     out = fopen (osm_path, "wb");
1843     if (out == NULL)
1844 	goto stop;
1845 
1846     if (journal_off)
1847       {
1848 	  /* disabling the journal: unsafe but faster */
1849 	  ret =
1850 	      sqlite3_exec (handle, "PRAGMA journal_mode = OFF", NULL, NULL,
1851 			    &sql_err);
1852 	  if (ret != SQLITE_OK)
1853 	    {
1854 		fprintf (stderr, "PRAGMA journal_mode=OFF error: %s\n",
1855 			 sql_err);
1856 		sqlite3_free (sql_err);
1857 		goto stop;
1858 	    }
1859       }
1860 
1861 /* resetting filtered nodes, ways and relations */
1862     if (!reset_filtered (handle))
1863 	goto stop;
1864 
1865 /* identifying filtered nodes */
1866     if (!filter_nodes (handle, mask, mask_len))
1867 	goto stop;
1868 
1869 /* identifying relations depending on other relations */
1870     if (!filter_rel_relations (handle))
1871 	goto stop;
1872 
1873 /* identifying ways depending on relations */
1874     if (!filter_way_relations (handle))
1875 	goto stop;
1876 
1877 /* identifying nodes depending on relations */
1878     if (!filter_node_relations (handle))
1879 	goto stop;
1880 
1881 /* identifying nodes depending on ways */
1882     if (!filter_node_ways (handle))
1883 	goto stop;
1884 
1885 /* writing the OSM header */
1886     fprintf (out, "<?xml version='1.0' encoding='UTF-8'?>\n");
1887     fprintf (out, "<osm version=\"0.6\" generator=\"splite2osm\">\n");
1888 
1889     fprintf (stderr, "OutNodes\n");
1890 /* exporting OSM NODES */
1891     if (!do_output_nodes (out, handle))
1892       {
1893 	  fprintf (stderr, "\nThe output OSM file is corrupted !!!\n");
1894 	  goto stop;
1895       }
1896 
1897     fprintf (stderr, "OutWays\n");
1898 /* exporting OSM WAYS */
1899     if (!do_output_ways (out, handle))
1900       {
1901 	  fprintf (stderr, "\nThe output OSM file is corrupted !!!\n");
1902 	  goto stop;
1903       }
1904 
1905     fprintf (stderr, "OutRelations\n");
1906 /* exporting OSM RELATIONS */
1907     if (!do_output_relations (out, handle))
1908       {
1909 	  fprintf (stderr, "\nThe output OSM file is corrupted !!!\n");
1910 	  goto stop;
1911       }
1912 
1913 /* writing the OSM footer */
1914     fprintf (out, "</osm>\n");
1915 
1916   stop:
1917     free (mask);
1918     sqlite3_close (handle);
1919     spatialite_cleanup_ex (cache);
1920     if (out != NULL)
1921 	fclose (out);
1922     spatialite_shutdown ();
1923     return 0;
1924 }
1925