1 /*
2 / Exif.cpp
3 / methods related to EXIF import and XmlBLOB import/export
4 /
5 / version 1.7, 2013 May 8
6 /
7 / Author: Sandro Furieri a-furieri@lqt.it
8 /
9 / Copyright (C) 2008-2013  Alessandro Furieri
10 /
11 /    This program is free software: you can redistribute it and/or modify
12 /    it under the terms of the GNU General Public License as published by
13 /    the Free Software Foundation, either version 3 of the License, or
14 /    (at your option) any later version.
15 /
16 /    This program is distributed in the hope that it will be useful,
17 /    but WITHOUT ANY WARRANTY; without even the implied warranty of
18 /    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 /    GNU General Public License for more details.
20 /
21 /    You should have received a copy of the GNU General Public License
22 /    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 /
24 */
25 
26 #include "Classdef.h"
27 
28 #include <sys/types.h>
29 #if defined(_WIN32) && !defined(__MINGW32__)
30 #include <io.h>
31 #include <direct.h>
32 #else
33 #include <dirent.h>
34 #endif
35 #include <float.h>
36 
37 #include <wx/filename.h>
38 
39 #include <spatialite/gg_dxf.h>
40 
41 #if defined(_WIN32) && !defined(__MINGW32__)
42 #define strcasecmp	_stricmp
43 #endif
44 
ImportExifPhotos(wxString & path,bool folder,bool metadata,bool gps_only)45 void MyFrame::ImportExifPhotos(wxString & path, bool folder, bool metadata,
46                                bool gps_only)
47 {
48 //
49 // trying to import EXIF photos
50 //
51   int cnt;
52   char msg[256];
53   ::wxBeginBusyCursor();
54   if (CheckExifTables() == false)
55     {
56       ::wxEndBusyCursor();
57       wxMessageBox(wxT
58                    ("An EXIF table is already defined, but has incompatibles columns"),
59                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
60       return;
61     }
62   if (folder == true)
63     cnt = ExifLoadDir(path, gps_only, metadata);
64   else
65     cnt = ExifLoadFile(path, gps_only, metadata);
66   ::wxEndBusyCursor();
67   sprintf(msg, "%d EXIF photo%s succesfully inserted into the DB\n", cnt,
68           (cnt > 1) ? "s where" : " was");
69   wxMessageBox(wxString::FromUTF8(msg), wxT("spatialite_gui"),
70                wxOK | wxICON_INFORMATION, this);
71   InitTableTree();
72 }
73 
CheckExifTables()74 bool MyFrame::CheckExifTables()
75 {
76 //
77 // creates the EXIF DB tables / or checks existing ones for validity
78 //
79   int ret;
80   wxString sql;
81   char xsql[1024];
82   char *errMsg;
83   bool ok_photoId;
84   bool ok_photo;
85   bool ok_pixelX;
86   bool ok_pixelY;
87   bool ok_cameraMake;
88   bool ok_cameraModel;
89   bool ok_shotDateTime;
90   bool ok_gpsGeometry;
91   bool ok_gpsDirection;
92   bool ok_gpsTimestamp;
93   bool ok_fromPath;
94   bool ok_tagId;
95   bool ok_tagName;
96   bool ok_gpsTag;
97   bool ok_valueType;
98   bool ok_typeName;
99   bool ok_countValues;
100   bool ok_valueIndex;
101   bool ok_byteValue;
102   bool ok_stringValue;
103   bool ok_numValue;
104   bool ok_numValueBis;
105   bool ok_doubleValue;
106   bool ok_humanReadable;
107   bool err_pk;
108   bool ok_photoIdPk;
109   bool ok_tagIdPk;
110   bool ok_valueIndexPk;
111   bool pKey;
112   const char *name;
113   int i;
114   char **results;
115   int rows;
116   int columns;
117 // creating the ExifPhoto table
118   sql = wxT("CREATE TABLE IF NOT EXISTS ExifPhoto (\n");
119   sql += wxT("PhotoId INTEGER PRIMARY KEY AUTOINCREMENT,\n");
120   sql += wxT("Photo BLOB NOT NULL,\n");
121   sql += wxT("PixelX INTEGER,\n");
122   sql += wxT("PixelY INTEGER,\n");
123   sql += wxT("CameraMake TEXT,\n");
124   sql += wxT("CameraModel TEXT,\n");
125   sql += wxT("ShotDateTime DOUBLE,\n");
126   sql += wxT("GpsGeometry BLOB,\n");
127   sql += wxT("GpsDirection DOUBLE, ");
128   sql += wxT("GpsSatellites TEXT,\n");
129   sql += wxT("GpsTimestamp DOUBLE,\n");
130   sql += wxT("FromPath TEXT");
131   sql += wxT(")");
132   strcpy(xsql, sql.ToUTF8());
133   ret = sqlite3_exec(SqliteHandle, xsql, NULL, NULL, &errMsg);
134   if (ret != SQLITE_OK)
135     {
136       wxMessageBox(wxT("CREATE TABLE ExifPhoto error: ") +
137                    wxString::FromUTF8(errMsg), wxT("spatialite_gui"),
138                    wxOK | wxICON_ERROR, this);
139       sqlite3_free(errMsg);
140       goto abort;
141     }
142 // checking the ExifPhoto table for sanity
143   ok_photoId = false;
144   ok_photo = false;
145   ok_pixelX = false;
146   ok_pixelY = false;
147   ok_cameraMake = false;
148   ok_cameraModel = false;
149   ok_shotDateTime = false;
150   ok_gpsGeometry = false;
151   ok_gpsDirection = false;
152   ok_gpsTimestamp = false;
153   ok_fromPath = false;
154   ok_photoIdPk = false;
155   err_pk = false;
156   strcpy(xsql, "PRAGMA table_info(ExifPhoto)");
157   ret =
158     sqlite3_get_table(SqliteHandle, xsql, &results, &rows, &columns, &errMsg);
159   if (ret != SQLITE_OK)
160     {
161       wxMessageBox(wxT("PRAGMA table_info(ExifPhoto) error: ") +
162                    wxString::FromUTF8(errMsg), wxT("spatialite_gui"),
163                    wxOK | wxICON_ERROR, this);
164       sqlite3_free(errMsg);
165       goto abort;
166     }
167   if (rows < 1)
168     ;
169   else
170     {
171       for (i = 1; i <= rows; i++)
172         {
173           name = results[(i * columns) + 1];
174           if (atoi(results[(i * columns) + 5]) == 0)
175             pKey = false;
176           else
177             pKey = true;
178           if (strcasecmp(name, "PhotoId") == 0)
179             ok_photoId = true;
180           if (strcasecmp(name, "Photo") == 0)
181             ok_photo = true;
182           if (strcasecmp(name, "PixelX") == 0)
183             ok_pixelX = true;
184           if (strcasecmp(name, "PixelY") == 0)
185             ok_pixelY = true;
186           if (strcasecmp(name, "CameraMake") == 0)
187             ok_cameraMake = true;
188           if (strcasecmp(name, "CameraModel") == 0)
189             ok_cameraModel = true;
190           if (strcasecmp(name, "ShotDateTime") == 0)
191             ok_shotDateTime = true;
192           if (strcasecmp(name, "GpsGeometry") == 0)
193             ok_gpsGeometry = true;
194           if (strcasecmp(name, "GpsDirection") == 0)
195             ok_gpsDirection = true;
196           if (strcasecmp(name, "GpsTimestamp") == 0)
197             ok_gpsTimestamp = true;
198           if (strcasecmp(name, "FromPath") == 0)
199             ok_fromPath = true;
200           if (pKey == true)
201             {
202               if (strcasecmp(name, "PhotoId") == 0)
203                 ok_photoIdPk = true;
204               else
205                 err_pk = true;
206             }
207         }
208     }
209   sqlite3_free_table(results);
210   if (ok_photoId == true && ok_photo == true && ok_pixelX == true
211       && ok_pixelY == true && ok_cameraMake == true && ok_cameraModel == true
212       && ok_shotDateTime == true && ok_gpsGeometry == true
213       && ok_gpsDirection == true && ok_gpsTimestamp == true
214       && ok_fromPath == true && ok_photoIdPk == true && err_pk == false)
215     ;
216   else
217     {
218       wxMessageBox(wxT
219                    ("ERROR: table ExifPhoto already exists, but has incompatible columns"),
220                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
221       sqlite3_free(errMsg);
222       goto abort;
223     }
224 // creating the ExifTags table
225   sql = wxT("CREATE TABLE IF NOT EXISTS ExifTags (\n");
226   sql += wxT("PhotoId INTEGER NOT NULL,\n");
227   sql += wxT("TagId INTEGER NOT NULL,\n");
228   sql += wxT("TagName TEXT NOT NULL,\n");
229   sql += wxT("GpsTag INTEGER NOT NULL CHECK (GpsTag IN (0, 1)),\n");
230   sql +=
231     wxT
232     ("ValueType INTEGER NOT NULL CHECK (ValueType IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)),\n");
233   sql += wxT("TypeName TEXT NOT NULL,\n");
234   sql += wxT("CountValues INTEGER NOT NULL,\n");
235   sql += wxT("PRIMARY KEY (PhotoId, TagId)");
236   sql += wxT(")");
237   strcpy(xsql, sql.ToUTF8());
238   ret = sqlite3_exec(SqliteHandle, xsql, NULL, NULL, &errMsg);
239   if (ret != SQLITE_OK)
240     {
241       wxMessageBox(wxT("CREATE TABLE ExifTags error: ") +
242                    wxString::FromUTF8(errMsg), wxT("spatialite_gui"),
243                    wxOK | wxICON_ERROR, this);
244       sqlite3_free(errMsg);
245       goto abort;
246     }
247 // checking the ExifTags table for sanity
248   ok_photoId = false;
249   ok_tagId = false;
250   ok_tagName = false;
251   ok_gpsTag = false;
252   ok_valueType = false;
253   ok_typeName = false;
254   ok_countValues = false;
255   ok_photoIdPk = false;
256   ok_tagIdPk = false;
257   err_pk = false;
258   strcpy(xsql, "PRAGMA table_info(ExifTags)");
259   ret =
260     sqlite3_get_table(SqliteHandle, xsql, &results, &rows, &columns, &errMsg);
261   if (ret != SQLITE_OK)
262     {
263       wxMessageBox(wxT("PRAGMA table_info(ExifTags) error: ") +
264                    wxString::FromUTF8(errMsg), wxT("spatialite_gui"),
265                    wxOK | wxICON_ERROR, this);
266       sqlite3_free(errMsg);
267       goto abort;
268     }
269   if (rows < 1)
270     ;
271   else
272     {
273       for (i = 1; i <= rows; i++)
274         {
275           name = results[(i * columns) + 1];
276           if (atoi(results[(i * columns) + 5]) == 0)
277             pKey = false;
278           else
279             pKey = true;
280           if (strcasecmp(name, "PhotoId") == 0)
281             ok_photoId = true;
282           if (strcasecmp(name, "TagId") == 0)
283             ok_tagId = true;
284           if (strcasecmp(name, "TagName") == 0)
285             ok_tagName = true;
286           if (strcasecmp(name, "GpsTag") == 0)
287             ok_gpsTag = true;
288           if (strcasecmp(name, "ValueType") == 0)
289             ok_valueType = true;
290           if (strcasecmp(name, "TypeName") == 0)
291             ok_typeName = true;
292           if (strcasecmp(name, "CountValues") == 0)
293             ok_countValues = true;
294           if (pKey == true)
295             {
296               if (strcasecmp(name, "PhotoId") == 0)
297                 ok_photoIdPk = true;
298               else if (strcasecmp(name, "TagId") == 0)
299                 ok_tagIdPk = true;
300               else
301                 err_pk = true;
302             }
303         }
304     }
305   sqlite3_free_table(results);
306   if (ok_photoId == true && ok_tagId == true && ok_tagName == true
307       && ok_gpsTag == true && ok_valueType == true && ok_typeName == true
308       && ok_countValues == true && ok_photoIdPk == true && ok_tagIdPk == true
309       && err_pk == false)
310     ;
311   else
312     {
313       wxMessageBox(wxT
314                    ("ERROR: table ExifTags already exists, but has incompatible columns"),
315                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
316       sqlite3_free(errMsg);
317       goto abort;
318     }
319 // creating the ExifValues table
320   sql = wxT("CREATE TABLE IF NOT EXISTS ExifValues (\n");
321   sql += wxT("PhotoId INTEGER NOT NULL,\n");
322   sql += wxT("TagId INTEGER NOT NULL,\n");
323   sql += wxT("ValueIndex INTEGER NOT NULL,\n");
324   sql += wxT("ByteValue BLOB,\n");
325   sql += wxT("StringValue TEXT,\n");
326   sql += wxT("NumValue INTEGER,\n");
327   sql += wxT("NumValueBis INTEGER,\n");
328   sql += wxT("DoubleValue DOUBLE,\n");
329   sql += wxT("HumanReadable TEXT,\n");
330   sql += wxT("PRIMARY KEY (PhotoId, TagId, ValueIndex)");
331   sql += wxT(")");
332   strcpy(xsql, sql.ToUTF8());
333   ret = sqlite3_exec(SqliteHandle, xsql, NULL, NULL, &errMsg);
334   if (ret != SQLITE_OK)
335     {
336       wxMessageBox(wxT("CREATE TABLE ExifValues error: ") +
337                    wxString::FromUTF8(errMsg), wxT("spatialite_gui"),
338                    wxOK | wxICON_ERROR, this);
339       sqlite3_free(errMsg);
340       goto abort;
341     }
342 // checking the ExifValues table for sanity
343   ok_photoId = false;
344   ok_tagId = false;
345   ok_valueIndex = false;
346   ok_byteValue = false;
347   ok_stringValue = false;
348   ok_numValue = false;
349   ok_numValueBis = false;
350   ok_doubleValue = false;
351   ok_humanReadable = false;
352   ok_photoIdPk = false;
353   ok_tagIdPk = false;
354   ok_valueIndexPk = false;
355   err_pk = false;
356   strcpy(xsql, "PRAGMA table_info(ExifValues)");
357   ret =
358     sqlite3_get_table(SqliteHandle, xsql, &results, &rows, &columns, &errMsg);
359   if (ret != SQLITE_OK)
360     {
361       wxMessageBox(wxT("PRAGMA table_info(ExifValues) error: ") +
362                    wxString::FromUTF8(errMsg), wxT("spatialite_gui"),
363                    wxOK | wxICON_ERROR, this);
364       sqlite3_free(errMsg);
365       goto abort;
366     }
367   if (rows < 1)
368     ;
369   else
370     {
371       for (i = 1; i <= rows; i++)
372         {
373           name = results[(i * columns) + 1];
374           if (atoi(results[(i * columns) + 5]) == 0)
375             pKey = false;
376           else
377             pKey = true;
378           if (strcasecmp(name, "PhotoId") == 0)
379             ok_photoId = true;
380           if (strcasecmp(name, "TagId") == 0)
381             ok_tagId = true;
382           if (strcasecmp(name, "ValueIndex") == 0)
383             ok_valueIndex = true;
384           if (strcasecmp(name, "ByteValue") == 0)
385             ok_byteValue = true;
386           if (strcasecmp(name, "StringValue") == 0)
387             ok_stringValue = true;
388           if (strcasecmp(name, "NumValue") == 0)
389             ok_numValue = true;
390           if (strcasecmp(name, "NumValueBis") == 0)
391             ok_numValueBis = true;
392           if (strcasecmp(name, "DoubleValue") == 0)
393             ok_doubleValue = true;
394           if (strcasecmp(name, "HumanReadable") == 0)
395             ok_humanReadable = true;
396           if (pKey == true)
397             {
398               if (strcasecmp(name, "PhotoId") == 0)
399                 ok_photoIdPk = true;
400               else if (strcasecmp(name, "TagId") == 0)
401                 ok_tagIdPk = true;
402               else if (strcasecmp(name, "ValueIndex") == 0)
403                 ok_valueIndexPk = true;
404               else
405                 err_pk = true;
406             }
407         }
408     }
409   sqlite3_free_table(results);
410   if (ok_photoId == true && ok_tagId == true && ok_valueIndex == true
411       && ok_byteValue == true && ok_stringValue == true && ok_numValue == true
412       && ok_numValueBis == true && ok_doubleValue == true
413       && ok_humanReadable == true && ok_photoIdPk == true && ok_tagIdPk == true
414       && ok_valueIndexPk == true && err_pk == false)
415     ;
416   else
417     {
418       wxMessageBox(wxT
419                    ("ERROR: table ExifValues already exists, but has incompatible columns"),
420                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
421       sqlite3_free(errMsg);
422       goto abort;
423     }
424 // creating the ExifView view
425   sql = wxT("CREATE VIEW IF NOT EXISTS ExifMetadata AS\n");
426   sql += wxT("SELECT p.PhotoId AS PhotoId, ");
427   sql += wxT("t.TagId AS TagId, ");
428   sql += wxT("t.TagName AS TagName,");
429   sql += wxT("t.GpsTag AS GpsTag,\n");
430   sql += wxT("t.ValueType AS ValueType,");
431   sql += wxT("t.TypeName AS TypeName, ");
432   sql += wxT("t.CountValues AS CountValues, ");
433   sql += wxT("v.ValueIndex AS ValueIndex,\n");
434   sql += wxT("v.ByteValue AS ByteValue, ");
435   sql += wxT("v.StringValue AS StringValue, ");
436   sql += wxT("v.NumValue AS NumValue, ");
437   sql += wxT("v.NumValueBis AS NumValueBis,\n");
438   sql += wxT("v.DoubleValue AS DoubleValue, ");
439   sql += wxT("v.HumanReadable AS HumanReadable\n");
440   sql += wxT("FROM ExifPhoto AS p, ExifTags AS t, ExifValues AS v\n");
441   sql +=
442     wxT
443     ("WHERE t.PhotoId = p.PhotoId AND v.PhotoId = t.PhotoId AND v.TagId = t.TagId");
444   strcpy(xsql, sql.ToUTF8());
445   ret = sqlite3_exec(SqliteHandle, xsql, NULL, NULL, &errMsg);
446   if (ret != SQLITE_OK)
447     {
448       wxMessageBox(wxT("CREATE VIEW ExifMetadata error: ") +
449                    wxString::FromUTF8(errMsg), wxT("spatialite_gui"),
450                    wxOK | wxICON_ERROR, this);
451       sqlite3_free(errMsg);
452       goto abort;
453     }
454   return true;
455 abort:
456   return false;
457 }
458 
ExifLoadDir(wxString & path,bool gps_only,bool metadata)459 int MyFrame::ExifLoadDir(wxString & path, bool gps_only, bool metadata)
460 {
461 //
462 // importing EXIF files from a whole DIRECTORY
463 //
464 #if defined(_WIN32) && !defined(__MINGW32__)
465 /* Visual Studio .NET */
466   struct _finddata_t c_file;
467   intptr_t hFile;
468   int cnt = 0;
469   wxString filePath;
470   if (_chdir(path.ToUTF8()) < 0)
471     return 0;
472   if ((hFile = _findfirst("*.*", &c_file)) == -1L)
473     ;
474   else
475     {
476       while (1)
477         {
478           if ((c_file.attrib & _A_RDONLY) == _A_RDONLY
479               || (c_file.attrib & _A_NORMAL) == _A_NORMAL)
480             {
481               filePath = path;
482               filePath += wxT("/") + wxString::FromUTF8(c_file.name);
483               cnt += ExifLoadFile(filePath, gps_only, metadata);
484             }
485           if (_findnext(hFile, &c_file) != 0)
486             break;
487         };
488       _findclose(hFile);
489     }
490   return cnt;
491 #else
492 /* not Visual Studio .NET */
493   int cnt = 0;
494   wxString filePath;
495   struct dirent *entry;
496   DIR *dir = opendir(path.ToUTF8());
497   if (!dir)
498     return 0;
499   while (1)
500     {
501       // scanning dir-entries
502       entry = readdir(dir);
503       if (!entry)
504         break;
505       filePath = path;
506       filePath += wxT("/") + wxString::FromUTF8(entry->d_name);
507       cnt += ExifLoadFile(filePath, gps_only, metadata);
508     }
509   closedir(dir);
510   return cnt;
511 #endif
512 }
513 
ExifLoadFile(wxString & path,bool gps_only,bool metadata)514 int MyFrame::ExifLoadFile(wxString & path, bool gps_only, bool metadata)
515 {
516 //
517 // importing a single EXIF file
518 //
519   FILE *fl;
520   int sz = 0;
521   int rd;
522   int loaded = 0;
523   unsigned char *blob = NULL;
524   gaiaExifTagListPtr tag_list = NULL;
525   fl = fopen(path.ToUTF8(), "rb");
526   if (!fl)
527     return 0;
528   if (fseek(fl, 0, SEEK_END) == 0)
529     sz = ftell(fl);
530   if (sz > 14)
531     {
532       blob = (unsigned char *) malloc(sz);
533       rewind(fl);
534       rd = fread(blob, 1, sz, fl);
535       if (rd == sz)
536         {
537           tag_list = gaiaGetExifTags(blob, sz);
538           if (tag_list)
539             {
540               if (gps_only && IsExifGps(tag_list) == false)
541                 goto stop;
542               if (UpdateExifTables(blob, sz, tag_list, metadata, path) == false)
543                 goto stop;
544               loaded = 1;
545             }
546         }
547     }
548 stop:
549   if (blob)
550     free(blob);
551   if (tag_list)
552     gaiaExifTagsFree(tag_list);
553   fclose(fl);
554   return loaded;
555 }
556 
IsExifGps(gaiaExifTagListPtr tag_list)557 bool MyFrame::IsExifGps(gaiaExifTagListPtr tag_list)
558 {
559 //
560 // checks if this one is a GPS-tagged EXIF
561 //
562   bool gps_lat = false;
563   bool gps_long = false;
564   gaiaExifTagPtr pT = tag_list->First;
565   while (pT)
566     {
567       if (pT->Gps && pT->TagId == 0x04)
568         gps_long = true;
569       if (pT->Gps && pT->TagId == 0x02)
570         gps_lat = true;
571       if (gps_long == true && gps_lat == true)
572         return true;
573       pT = pT->Next;
574     }
575   return false;
576 }
577 
UpdateExifTables(unsigned char * blob,int sz,gaiaExifTagListPtr tag_list,bool metadata,wxString & path)578 bool MyFrame::UpdateExifTables(unsigned char *blob, int sz,
579                                gaiaExifTagListPtr tag_list, bool metadata,
580                                wxString & path)
581 {
582 //
583 // inserting an EXIF photo into the DB
584 //
585   int i;
586   int iv;
587   bool ok;
588   int xok;
589   int ok_human;
590   char tag_name[128];
591   gaiaExifTagPtr pT;
592   int ret;
593   char sql[1024];
594   char human[1024];
595   wxString make;
596   wxString model;
597   wxString satellites;
598   wxString date;
599   wxString timestamp;
600   char *errMsg = NULL;
601   sqlite3_stmt *stmt;
602   sqlite3_int64 pk = 0;
603   sqlite3_int64 val64;
604   double dblval;
605   const char *type_desc;
606   double longitude;
607   double latitude;
608   gaiaGeomCollPtr geom;
609   unsigned char *geoblob;
610   int geosize;
611 // starts a transaction
612   strcpy(sql, "BEGIN");
613   ret = sqlite3_exec(SqliteHandle, sql, NULL, NULL, &errMsg);
614   if (ret != SQLITE_OK)
615     {
616       wxMessageBox(wxT("BEGIN error: ") + wxString::FromUTF8(errMsg),
617                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
618       sqlite3_free(errMsg);
619       goto abort;
620     }
621 // feeding the ExifPhoto table; preparing the SQL statement
622   strcpy(sql,
623          "INSERT INTO ExifPhoto (PhotoId, Photo, PixelX, PixelY, CameraMake, CameraModel, ");
624   strcat(sql,
625          "ShotDateTime, GpsGeometry, GpsDirection, GpsSatellites, GpsTimestamp, FromPath) ");
626   strcat(sql,
627          "VALUES (NULL, ?, ?, ?, ?, ?, JulianDay(?), ?, ?, ?, JulianDay(?), ?)");
628   ret = sqlite3_prepare_v2(SqliteHandle, sql, strlen(sql), &stmt, NULL);
629   if (ret != SQLITE_OK)
630     {
631       wxMessageBox(wxT("INSERT INTO ExifPhoto error: ") +
632                    wxString::FromUTF8(sqlite3_errmsg(SqliteHandle)),
633                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
634       goto abort;
635     }
636   sqlite3_bind_blob(stmt, 1, blob, sz, SQLITE_STATIC);
637   val64 = GetPixelX(tag_list, &ok);
638   if (ok == true)
639     sqlite3_bind_int64(stmt, 2, val64);
640   else
641     sqlite3_bind_null(stmt, 2);
642   val64 = GetPixelY(tag_list, &ok);
643   if (ok == true)
644     sqlite3_bind_int64(stmt, 3, val64);
645   else
646     sqlite3_bind_null(stmt, 3);
647   GetMake(tag_list, make, &ok);
648   if (ok == true)
649     sqlite3_bind_text(stmt, 4, make.ToUTF8(), make.Len(), SQLITE_TRANSIENT);
650   else
651     sqlite3_bind_null(stmt, 4);
652   GetModel(tag_list, model, &ok);
653   if (ok == true)
654     sqlite3_bind_text(stmt, 5, model.ToUTF8(), model.Len(), SQLITE_TRANSIENT);
655   else
656     sqlite3_bind_null(stmt, 5);
657   GetDate(tag_list, date, &ok);
658   if (ok == true)
659     sqlite3_bind_text(stmt, 6, date.ToUTF8(), date.Len(), SQLITE_TRANSIENT);
660   else
661     sqlite3_bind_text(stmt, 6, "0000-00-00 00:00:00", 19, SQLITE_TRANSIENT);
662   GetGpsCoords(tag_list, &longitude, &latitude, &ok);
663   if (ok == true)
664     {
665       geom = gaiaAllocGeomColl();
666       geom->Srid = 4326;
667       gaiaAddPointToGeomColl(geom, longitude, latitude);
668       gaiaToSpatiaLiteBlobWkb(geom, &geoblob, &geosize);
669       gaiaFreeGeomColl(geom);
670       sqlite3_bind_blob(stmt, 7, geoblob, geosize, SQLITE_TRANSIENT);
671       free(geoblob);
672   } else
673     sqlite3_bind_null(stmt, 7);
674   dblval = GetGpsDirection(tag_list, &ok);
675   if (ok == true)
676     sqlite3_bind_double(stmt, 8, dblval);
677   else
678     sqlite3_bind_null(stmt, 8);
679   GetGpsSatellites(tag_list, satellites, &ok);
680   if (ok == true)
681     sqlite3_bind_text(stmt, 9, satellites.ToUTF8(), satellites.Len(),
682                       SQLITE_TRANSIENT);
683   else
684     sqlite3_bind_null(stmt, 9);
685   GetGpsTimestamp(tag_list, timestamp, &ok);
686   if (ok == true)
687     sqlite3_bind_text(stmt, 10, timestamp.ToUTF8(), timestamp.Len(),
688                       SQLITE_TRANSIENT);
689   else
690     sqlite3_bind_text(stmt, 10, "0000-00-00 00:00:00", 19, SQLITE_TRANSIENT);
691   sqlite3_bind_text(stmt, 11, path.ToUTF8(), path.Len(), SQLITE_TRANSIENT);
692   ret = sqlite3_step(stmt);
693   if (ret == SQLITE_DONE || ret == SQLITE_ROW)
694     ;
695   else
696     {
697       wxMessageBox(wxT("sqlite3_step() error: ") +
698                    wxString::FromUTF8(sqlite3_errmsg(SqliteHandle)),
699                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
700       sqlite3_finalize(stmt);
701       goto abort;
702     }
703   sqlite3_finalize(stmt);
704   pk = sqlite3_last_insert_rowid(SqliteHandle);
705   if (metadata)
706     {
707       // feeding the ExifTags table; preparing the SQL statement
708       strcpy(sql,
709              "INSERT OR IGNORE INTO ExifTags (PhotoId, TagId, TagName, GpsTag, ValueType, ");
710       strcat(sql, "TypeName, CountValues) VALUES (?, ?, ?, ?, ?, ?, ?)");
711       ret = sqlite3_prepare_v2(SqliteHandle, sql, strlen(sql), &stmt, NULL);
712       if (ret != SQLITE_OK)
713         {
714           wxMessageBox(wxT("INSERT INTO ExifTags error: ") +
715                        wxString::FromUTF8(sqlite3_errmsg(SqliteHandle)),
716                        wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
717           goto abort;
718         }
719       for (i = 0; i < gaiaGetExifTagsCount(tag_list); i++)
720         {
721           pT = gaiaGetExifTagByPos(tag_list, i);
722           if (pT)
723             {
724               gaiaExifTagGetName(pT, tag_name, 128);
725               switch (gaiaExifTagGetValueType(pT))
726                 {
727                   case 1:
728                     type_desc = "BYTE";
729                     break;
730                   case 2:
731                     type_desc = "STRING";
732                     break;
733                   case 3:
734                     type_desc = "SHORT";
735                     break;
736                   case 4:
737                     type_desc = "LONG";
738                     break;
739                   case 5:
740                     type_desc = "RATIONAL";
741                     break;
742                   case 6:
743                     type_desc = "SBYTE";
744                     break;
745                   case 7:
746                     type_desc = "UNDEFINED";
747                     break;
748                   case 8:
749                     type_desc = "SSHORT";
750                     break;
751                   case 9:
752                     type_desc = "SLONG";
753                     break;
754                   case 10:
755                     type_desc = "SRATIONAL";
756                     break;
757                   case 11:
758                     type_desc = "FLOAT";
759                     break;
760                   case 12:
761                     type_desc = "DOUBLE";
762                     break;
763                   default:
764                     type_desc = "UNKNOWN";
765                     break;
766                 };
767               // INSERTing an Exif Tag
768               sqlite3_reset(stmt);
769               sqlite3_clear_bindings(stmt);
770               sqlite3_bind_int64(stmt, 1, pk);
771               sqlite3_bind_int(stmt, 2, gaiaExifTagGetId(pT));
772               sqlite3_bind_text(stmt, 3, tag_name, strlen(tag_name),
773                                 SQLITE_STATIC);
774               sqlite3_bind_int(stmt, 4, gaiaIsExifGpsTag(pT));
775               sqlite3_bind_int(stmt, 5, gaiaExifTagGetValueType(pT));
776               sqlite3_bind_text(stmt, 6, type_desc, strlen(type_desc),
777                                 SQLITE_STATIC);
778               sqlite3_bind_int(stmt, 7, gaiaExifTagGetNumValues(pT));
779               ret = sqlite3_step(stmt);
780               if (ret == SQLITE_DONE || ret == SQLITE_ROW)
781                 ;
782               else
783                 {
784                   wxMessageBox(wxT("sqlite3_step() error: ") +
785                                wxString::FromUTF8(sqlite3_errmsg(SqliteHandle)),
786                                wxT("spatialite_gui"), wxOK | wxICON_ERROR,
787                                this);
788                   sqlite3_finalize(stmt);
789                   goto abort;
790                 }
791             }
792         }
793       sqlite3_finalize(stmt);
794       // feeding the ExifValues table; preparing the SQL statement
795       strcpy(sql,
796              "INSERT OR IGNORE INTO ExifValues (PhotoId, TagId, ValueIndex, ByteValue, ");
797       strcat(sql,
798              "StringValue, NumValue, NumValueBis, DoubleValue, HumanReadable) VALUES ");
799       strcat(sql, "(?, ?, ?, ?, ?, ?, ?, ?, ?)");
800       ret = sqlite3_prepare_v2(SqliteHandle, sql, strlen(sql), &stmt, NULL);
801       if (ret != SQLITE_OK)
802         {
803           wxMessageBox(wxT("NSERT INTO ExifValues error: ") +
804                        wxString::FromUTF8(sqlite3_errmsg(SqliteHandle)),
805                        wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
806           goto abort;
807         }
808       for (i = 0; i < gaiaGetExifTagsCount(tag_list); i++)
809         {
810           pT = gaiaGetExifTagByPos(tag_list, i);
811           if (pT)
812             {
813               gaiaExifTagGetHumanReadable(pT, human, 1024, &ok_human);
814               for (iv = 0; iv < gaiaExifTagGetNumValues(pT); iv++)
815                 {
816                   // INSERTing an Exif Tag
817                   sqlite3_reset(stmt);
818                   sqlite3_clear_bindings(stmt);
819                   sqlite3_bind_int64(stmt, 1, pk);
820                   sqlite3_bind_int(stmt, 2, gaiaExifTagGetId(pT));
821                   sqlite3_bind_int(stmt, 3, iv);
822                   if (gaiaExifTagGetValueType(pT) == 1
823                       || gaiaExifTagGetValueType(pT) == 6
824                       || gaiaExifTagGetValueType(pT) == 7)
825                     {
826                       sqlite3_bind_blob(stmt, 4, pT->ByteValue, pT->Count,
827                                         SQLITE_STATIC);
828                       sqlite3_bind_null(stmt, 5);
829                       sqlite3_bind_null(stmt, 6);
830                       sqlite3_bind_null(stmt, 7);
831                       sqlite3_bind_null(stmt, 8);
832                     }
833                   if (gaiaExifTagGetValueType(pT) == 2)
834                     {
835                       sqlite3_bind_null(stmt, 4);
836                       sqlite3_bind_text(stmt, 5, pT->StringValue,
837                                         strlen(pT->StringValue), SQLITE_STATIC);
838                       sqlite3_bind_null(stmt, 6);
839                       sqlite3_bind_null(stmt, 7);
840                       sqlite3_bind_null(stmt, 8);
841                     }
842                   if (gaiaExifTagGetValueType(pT) == 3)
843                     {
844                       sqlite3_bind_null(stmt, 4);
845                       sqlite3_bind_null(stmt, 5);
846                       val64 = gaiaExifTagGetShortValue(pT, iv, &xok);
847                       if (!ok)
848                         sqlite3_bind_null(stmt, 6);
849                       else
850                         sqlite3_bind_int64(stmt, 6, val64);
851                       sqlite3_bind_null(stmt, 7);
852                       sqlite3_bind_null(stmt, 8);
853                     }
854                   if (gaiaExifTagGetValueType(pT) == 4)
855                     {
856                       sqlite3_bind_null(stmt, 4);
857                       sqlite3_bind_null(stmt, 5);
858                       val64 = gaiaExifTagGetLongValue(pT, iv, &xok);
859                       if (!ok)
860                         sqlite3_bind_null(stmt, 6);
861                       else
862                         sqlite3_bind_int64(stmt, 6, val64);
863                       sqlite3_bind_null(stmt, 7);
864                       sqlite3_bind_null(stmt, 8);
865                     }
866                   if (gaiaExifTagGetValueType(pT) == 5)
867                     {
868                       sqlite3_bind_null(stmt, 4);
869                       sqlite3_bind_null(stmt, 5);
870                       val64 = gaiaExifTagGetRational1Value(pT, iv, &xok);
871                       if (!ok)
872                         sqlite3_bind_null(stmt, 6);
873                       else
874                         sqlite3_bind_int64(stmt, 6, val64);
875                       val64 = gaiaExifTagGetRational2Value(pT, iv, &xok);
876                       if (!ok)
877                         sqlite3_bind_null(stmt, 7);
878                       else
879                         sqlite3_bind_int64(stmt, 7, val64);
880                       dblval = gaiaExifTagGetRationalValue(pT, iv, &xok);
881                       if (!ok)
882                         sqlite3_bind_null(stmt, 8);
883                       else
884                         sqlite3_bind_double(stmt, 8, dblval);
885                     }
886                   if (gaiaExifTagGetValueType(pT) == 9)
887                     {
888                       sqlite3_bind_null(stmt, 4);
889                       sqlite3_bind_null(stmt, 5);
890                       val64 = gaiaExifTagGetSignedLongValue(pT, iv, &xok);
891                       if (!ok)
892                         sqlite3_bind_null(stmt, 6);
893                       else
894                         sqlite3_bind_int64(stmt, 6, val64);
895                       sqlite3_bind_null(stmt, 7);
896                       sqlite3_bind_null(stmt, 8);
897                     }
898                   if (gaiaExifTagGetValueType(pT) == 10)
899                     {
900                       sqlite3_bind_null(stmt, 4);
901                       sqlite3_bind_null(stmt, 5);
902                       val64 = gaiaExifTagGetSignedRational1Value(pT, iv, &xok);
903                       if (!ok)
904                         sqlite3_bind_null(stmt, 6);
905                       else
906                         sqlite3_bind_int64(stmt, 6, val64);
907                       val64 = gaiaExifTagGetSignedRational2Value(pT, iv, &xok);
908                       if (!ok)
909                         sqlite3_bind_null(stmt, 7);
910                       else
911                         sqlite3_bind_int64(stmt, 7, val64);
912                       dblval = gaiaExifTagGetSignedRationalValue(pT, iv, &xok);
913                       if (!ok)
914                         sqlite3_bind_null(stmt, 8);
915                       else
916                         sqlite3_bind_double(stmt, 8, dblval);
917                     }
918                   if (gaiaExifTagGetValueType(pT) == 11)
919                     {
920                       sqlite3_bind_null(stmt, 4);
921                       sqlite3_bind_null(stmt, 5);
922                       sqlite3_bind_null(stmt, 6);
923                       sqlite3_bind_null(stmt, 7);
924                       dblval = gaiaExifTagGetFloatValue(pT, iv, &xok);
925                       if (!ok)
926                         sqlite3_bind_null(stmt, 8);
927                       else
928                         sqlite3_bind_double(stmt, 8, dblval);
929                     }
930                   if (gaiaExifTagGetValueType(pT) == 12)
931                     {
932                       sqlite3_bind_null(stmt, 4);
933                       sqlite3_bind_null(stmt, 5);
934                       sqlite3_bind_null(stmt, 6);
935                       sqlite3_bind_null(stmt, 7);
936                       dblval = gaiaExifTagGetDoubleValue(pT, iv, &xok);
937                       if (!ok)
938                         sqlite3_bind_null(stmt, 8);
939                       else
940                         sqlite3_bind_double(stmt, 8, dblval);
941                     }
942                   if (!ok_human)
943                     sqlite3_bind_null(stmt, 9);
944                   else
945                     sqlite3_bind_text(stmt, 9, human, strlen(human),
946                                       SQLITE_STATIC);
947                   ret = sqlite3_step(stmt);
948                   if (ret == SQLITE_DONE || ret == SQLITE_ROW)
949                     ;
950                   else
951                     {
952                       wxMessageBox(wxT("sqlite3_step() error: ") +
953                                    wxString::FromUTF8(sqlite3_errmsg
954                                                       (SqliteHandle)),
955                                    wxT("spatialite_gui"), wxOK | wxICON_ERROR,
956                                    this);
957                       sqlite3_finalize(stmt);
958                       goto abort;
959                     }
960                   if (gaiaExifTagGetValueType(pT) == 1
961                       || gaiaExifTagGetValueType(pT) == 2
962                       || gaiaExifTagGetValueType(pT) == 6
963                       || gaiaExifTagGetValueType(pT) == 7)
964                     break;
965                   ok_human = 0;
966                 }
967             }
968         }
969       sqlite3_finalize(stmt);
970     }
971 // commits the transaction
972   strcpy(sql, "COMMIT");
973   ret = sqlite3_exec(SqliteHandle, sql, NULL, NULL, &errMsg);
974   if (ret != SQLITE_OK)
975     {
976       wxMessageBox(wxT("COMMIT error: ") + wxString::FromUTF8(errMsg),
977                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
978       sqlite3_free(errMsg);
979     }
980   return true;
981 abort:
982 // rolling back the transaction
983   strcpy(sql, "ROLLBACK");
984   ret = sqlite3_exec(SqliteHandle, sql, NULL, NULL, &errMsg);
985   if (ret != SQLITE_OK)
986     {
987       wxMessageBox(wxT("ROLLBACK error: ") + wxString::FromUTF8(errMsg),
988                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
989       sqlite3_free(errMsg);
990     }
991   return false;
992 }
993 
GetPixelX(gaiaExifTagListPtr tag_list,bool * ok)994 sqlite3_int64 MyFrame::GetPixelX(gaiaExifTagListPtr tag_list, bool * ok)
995 {
996 //
997 // trying to retrieve the ExifImageWidth
998 //
999   *ok = false;
1000   if (!tag_list)
1001     return 0;
1002   gaiaExifTagPtr tag = tag_list->First;
1003   while (tag)
1004     {
1005       if (tag->TagId == 0xA002)
1006         {
1007           // ok, this one is the ExifImageWidth tag
1008           if (tag->Type == 3 && tag->Count == 1)
1009             {
1010               *ok = true;
1011               return *(tag->ShortValues + 0);
1012           } else if (tag->Type == 4 && tag->Count == 1)
1013             {
1014               *ok = true;
1015               return *(tag->LongValues + 0);
1016             }
1017         }
1018       tag = tag->Next;
1019     }
1020   return false;
1021 }
1022 
GetPixelY(gaiaExifTagListPtr tag_list,bool * ok)1023 sqlite3_int64 MyFrame::GetPixelY(gaiaExifTagListPtr tag_list, bool * ok)
1024 {
1025 //
1026 // trying to retrieve the ExifImageLength
1027 //
1028   *ok = false;
1029   if (!tag_list)
1030     return 0;
1031   gaiaExifTagPtr tag = tag_list->First;
1032   while (tag)
1033     {
1034       if (tag->TagId == 0xA003)
1035         {
1036           // ok, this one is the ExifImageLength tag
1037           if (tag->Type == 3 && tag->Count == 1)
1038             {
1039               *ok = true;
1040               return *(tag->ShortValues + 0);
1041           } else if (tag->Type == 4 && tag->Count == 1)
1042             {
1043               *ok = true;
1044               return *(tag->LongValues + 0);
1045             }
1046         }
1047       tag = tag->Next;
1048     }
1049   return false;
1050 }
1051 
GetMake(gaiaExifTagListPtr tag_list,wxString & str,bool * ok)1052 void MyFrame::GetMake(gaiaExifTagListPtr tag_list, wxString & str, bool * ok)
1053 {
1054 //
1055 // trying to retrieve the Make
1056 //
1057   *ok = false;
1058   if (!tag_list)
1059     return;
1060   gaiaExifTagPtr tag = tag_list->First;
1061   while (tag)
1062     {
1063       if (tag->TagId == 0x010F)
1064         {
1065           // ok, this one is the Make tag
1066           if (tag->Type == 2)
1067             {
1068               *ok = true;
1069               str = wxString::FromUTF8(tag->StringValue);
1070               return;
1071             }
1072         }
1073       tag = tag->Next;
1074     }
1075   return;
1076 }
1077 
GetModel(gaiaExifTagListPtr tag_list,wxString & str,bool * ok)1078 void MyFrame::GetModel(gaiaExifTagListPtr tag_list, wxString & str, bool * ok)
1079 {
1080 //
1081 // trying to retrieve the Model
1082 //
1083   *ok = false;
1084   if (!tag_list)
1085     return;
1086   gaiaExifTagPtr tag = tag_list->First;
1087   while (tag)
1088     {
1089       if (tag->TagId == 0x0110)
1090         {
1091           // ok, this one is the Model tag
1092           if (tag->Type == 2)
1093             {
1094               *ok = true;
1095               str = wxString::FromUTF8(tag->StringValue);
1096               return;
1097             }
1098         }
1099       tag = tag->Next;
1100     }
1101   return;
1102 }
1103 
GetDate(gaiaExifTagListPtr tag_list,wxString & str,bool * ok)1104 void MyFrame::GetDate(gaiaExifTagListPtr tag_list, wxString & str, bool * ok)
1105 {
1106 //
1107 // trying to retrieve the Date
1108 //
1109   *ok = false;
1110   if (!tag_list)
1111     return;
1112   gaiaExifTagPtr tag = tag_list->First;
1113   while (tag)
1114     {
1115       if (tag->TagId == 0x9003)
1116         {
1117           // ok, this one is the DateTimeOriginal tag
1118           if (tag->Type == 2)
1119             {
1120               *ok = true;
1121               str = wxString::FromUTF8(tag->StringValue);
1122               if (str.Len() >= 19)
1123                 {
1124                   str.SetChar(4, '-');
1125                   str.SetChar(7, '-');
1126                 }
1127               return;
1128             }
1129         }
1130       tag = tag->Next;
1131     }
1132   return;
1133 }
1134 
GetGpsCoords(gaiaExifTagListPtr tag_list,double * longitude,double * latitude,bool * ok)1135 void MyFrame::GetGpsCoords(gaiaExifTagListPtr tag_list, double *longitude,
1136                            double *latitude, bool * ok)
1137 {
1138 //
1139 // trying to retrieve the GPS coordinates
1140 //
1141   char lat_ref = '\0';
1142   char long_ref = '\0';
1143   double lat_degs = DBL_MIN;
1144   double lat_mins = DBL_MIN;
1145   double lat_secs = DBL_MIN;
1146   double long_degs = DBL_MIN;
1147   double long_mins = DBL_MIN;
1148   double long_secs = DBL_MIN;
1149   double dblval;
1150   double sign;
1151   double dblLatitude = DBL_MIN;
1152   double dblLongitude = DBL_MIN;
1153   int xok;
1154   wxString str;
1155   *ok = false;
1156   if (!tag_list)
1157     return;
1158   gaiaExifTagPtr tag = tag_list->First;
1159   while (tag)
1160     {
1161       if (tag->Gps && tag->TagId == 0x01)
1162         {
1163           // ok, this one is the GPSLatitudeRef tag
1164           if (tag->Type == 2)
1165             lat_ref = *(tag->StringValue);
1166         }
1167       if (tag->Gps && tag->TagId == 0x03)
1168         {
1169           // ok, this one is the GPSLongitudeRef tag
1170           if (tag->Type == 2)
1171             long_ref = *(tag->StringValue);
1172         }
1173       if (tag->Gps && tag->TagId == 0x02)
1174         {
1175           // ok, this one is the GPSLatitude tag
1176           if (tag->Type == 5 && tag->Count == 3)
1177             {
1178               dblval = gaiaExifTagGetRationalValue(tag, 0, &xok);
1179               if (xok)
1180                 lat_degs = dblval;
1181               dblval = gaiaExifTagGetRationalValue(tag, 1, &xok);
1182               if (xok)
1183                 lat_mins = dblval;
1184               dblval = gaiaExifTagGetRationalValue(tag, 2, &xok);
1185               if (xok)
1186                 lat_secs = dblval;
1187             }
1188           if (tag->Type == 2)
1189             {
1190               str = wxString::FromUTF8(tag->StringValue);
1191               if (str.ToDouble(&dblval) == true)
1192                 dblLatitude = dblval;
1193             }
1194         }
1195       if (tag->Gps && tag->TagId == 0x04)
1196         {
1197           // ok, this one is the GPSLongitude tag
1198           if (tag->Type == 5 && tag->Count == 3)
1199             {
1200               dblval = gaiaExifTagGetRationalValue(tag, 0, &xok);
1201               if (xok)
1202                 long_degs = dblval;
1203               dblval = gaiaExifTagGetRationalValue(tag, 1, &xok);
1204               if (xok)
1205                 long_mins = dblval;
1206               dblval = gaiaExifTagGetRationalValue(tag, 2, &xok);
1207               if (xok)
1208                 long_secs = dblval;
1209             }
1210           if (tag->Type == 2)
1211             {
1212               str = wxString::FromUTF8(tag->StringValue);
1213               if (str.ToDouble(&dblval) == true)
1214                 dblLongitude = dblval;
1215             }
1216         }
1217       tag = tag->Next;
1218     }
1219   if ((lat_ref == 'N' || lat_ref == 'S' || long_ref == 'E' || long_ref == 'W')
1220       && lat_degs != DBL_MIN && lat_mins != DBL_MIN && lat_secs != DBL_MIN
1221       && long_degs != DBL_MIN && long_mins != DBL_MIN && long_secs != DBL_MIN)
1222     {
1223       *ok = true;
1224       if (lat_ref == 'S')
1225         sign = -1.0;
1226       else
1227         sign = 1.0;
1228       lat_degs = math_round(lat_degs * 1000000.0);
1229       lat_mins = math_round(lat_mins * 1000000.0);
1230       lat_secs = math_round(lat_secs * 1000000.0);
1231       dblval =
1232         math_round(lat_degs + (lat_mins / 60.0) +
1233                    (lat_secs / 3600.0)) * (sign / 1000000.0);
1234       *latitude = dblval;
1235       if (long_ref == 'W')
1236         sign = -1.0;
1237       else
1238         sign = 1.0;
1239       long_degs = math_round(long_degs * 1000000.0);
1240       long_mins = math_round(long_mins * 1000000.0);
1241       long_secs = math_round(long_secs * 1000000.0);
1242       dblval =
1243         math_round(long_degs + (long_mins / 60.0) +
1244                    (long_secs / 3600.0)) * (sign / 1000000.0);
1245       *longitude = dblval;
1246   } else if (dblLatitude != DBL_MIN && dblLongitude != DBL_MIN)
1247     {
1248       *ok = true;
1249       *latitude = dblLatitude;
1250       *longitude = dblLongitude;
1251     }
1252   return;
1253 }
1254 
GetGpsSatellites(gaiaExifTagListPtr tag_list,wxString & str,bool * ok)1255 void MyFrame::GetGpsSatellites(gaiaExifTagListPtr tag_list, wxString & str,
1256                                bool * ok)
1257 {
1258 //
1259 // trying to retrieve the GPSSatellites
1260 //
1261   *ok = false;
1262   if (!tag_list)
1263     return;
1264   gaiaExifTagPtr tag = tag_list->First;
1265   while (tag)
1266     {
1267       if (tag->Gps && tag->TagId == 0x08)
1268         {
1269           // ok, this one is the GPSSatellites tag
1270           if (tag->Type == 2)
1271             {
1272               *ok = true;
1273               str = wxString::FromUTF8(tag->StringValue);
1274               return;
1275             }
1276         }
1277       tag = tag->Next;
1278     }
1279   return;
1280 }
1281 
GetGpsDirection(gaiaExifTagListPtr tag_list,bool * ok)1282 double MyFrame::GetGpsDirection(gaiaExifTagListPtr tag_list, bool * ok)
1283 {
1284 //
1285 // trying to retrieve the GPS direction
1286 //
1287   char dir_ref = '\0';
1288   double direction = DBL_MIN;
1289   double dblval;
1290   int xok;
1291   *ok = false;
1292   if (!tag_list)
1293     return direction;
1294   gaiaExifTagPtr tag = tag_list->First;
1295   while (tag)
1296     {
1297       if (tag->Gps && tag->TagId == 0x10)
1298         {
1299           // ok, this one is the GPSDirectionRef tag
1300           if (tag->Type == 2)
1301             dir_ref = *(tag->StringValue);
1302         }
1303       if (tag->Gps && tag->TagId == 0x11)
1304         {
1305           // ok, this one is the GPSDirection tag
1306           if (tag->Type == 5 && tag->Count == 1)
1307             {
1308               dblval = gaiaExifTagGetRationalValue(tag, 0, &xok);
1309               if (xok)
1310                 direction = dblval;
1311             }
1312         }
1313       tag = tag->Next;
1314     }
1315   if ((dir_ref == 'T' || dir_ref == 'M') && direction != DBL_MIN)
1316     *ok = true;
1317   return direction;
1318 }
1319 
GetGpsTimestamp(gaiaExifTagListPtr tag_list,wxString & str,bool * ok)1320 void MyFrame::GetGpsTimestamp(gaiaExifTagListPtr tag_list, wxString & str,
1321                               bool * ok)
1322 {
1323 //
1324 // trying to retrieve the GPS Timestamp
1325 //
1326   char date[16];
1327   char timestamp[32];
1328   double hours = DBL_MIN;
1329   double mins = DBL_MIN;
1330   double secs = DBL_MIN;
1331   double dblval;
1332   int xok;
1333   int hh;
1334   int mm;
1335   int ss;
1336   int millis;
1337   *ok = false;
1338   if (!tag_list)
1339     return;
1340   strcpy(date, "0000-00-00");
1341   gaiaExifTagPtr tag = tag_list->First;
1342   while (tag)
1343     {
1344       if (tag->Gps && tag->TagId == 0x1D)
1345         {
1346           // ok, this one is the GPSDateStamp tag
1347           if (tag->Type == 2)
1348             {
1349               strcpy(date, tag->StringValue);
1350               date[4] = '-';
1351               date[7] = '-';
1352             }
1353         }
1354       if (tag->Gps && tag->TagId == 0x07)
1355         {
1356           // ok, this one is the GPSTimeStamp tag
1357           if (tag->Type == 5 && tag->Count == 3)
1358             {
1359               dblval = gaiaExifTagGetRationalValue(tag, 0, &xok);
1360               if (xok)
1361                 hours = dblval;
1362               dblval = gaiaExifTagGetRationalValue(tag, 1, &xok);
1363               if (xok)
1364                 mins = dblval;
1365               dblval = gaiaExifTagGetRationalValue(tag, 2, &xok);
1366               if (xok)
1367                 secs = dblval;
1368             }
1369         }
1370       tag = tag->Next;
1371     }
1372   if (hours != DBL_MIN && mins != DBL_MIN && secs != DBL_MIN)
1373     {
1374       *ok = true;
1375       hh = (int) floor(hours);
1376       mm = (int) floor(mins);
1377       ss = (int) floor(secs);
1378       millis = (int) ((secs - ss) * 1000);
1379       sprintf(timestamp, "%s %02d:%02d:%02d.%03d", date, hh, mm, ss, millis);
1380       str = wxString::FromUTF8(timestamp);
1381     }
1382   return;
1383 }
1384 
ImportXmlDocuments(wxString & path,bool folder,wxString & suffix,wxString & table,wxString & pkName,wxString & xmlColumn,wxString & inPathColumn,wxString & schemaUriColumn,wxString & parseErrColumn,wxString & validateErrColumn,int compressed,const char * schemaURI,bool isInternalSchemaUri)1385 void MyFrame::ImportXmlDocuments(wxString & path, bool folder,
1386                                  wxString & suffix, wxString & table,
1387                                  wxString & pkName, wxString & xmlColumn,
1388                                  wxString & inPathColumn,
1389                                  wxString & schemaUriColumn,
1390                                  wxString & parseErrColumn,
1391                                  wxString & validateErrColumn, int compressed,
1392                                  const char *schemaURI,
1393                                  bool isInternalSchemaUri)
1394 {
1395 //
1396 // trying to import XML Documents
1397 //
1398   int cnt;
1399   char msg[256];
1400   wxString sql;
1401   sqlite3_stmt *stmt;
1402   char *errMsg;
1403   char xsql[8192];
1404   char *qname;
1405   int ret;
1406   int failed;
1407   if (CheckOrCreateXmlTable
1408       (table, pkName, xmlColumn, inPathColumn, schemaUriColumn, parseErrColumn,
1409        validateErrColumn) == false)
1410     return;
1411 // preparing the SQL INSERT statement
1412   sql = wxT("INSERT OR IGNORE INTO \"");
1413   strcpy(xsql, table.ToUTF8());
1414   qname = gaiaDoubleQuotedSql(xsql);
1415   sql += wxString::FromUTF8(qname);
1416   free(qname);
1417   sql += wxT("\" (\"");
1418   strcpy(xsql, pkName.ToUTF8());
1419   qname = gaiaDoubleQuotedSql(xsql);
1420   sql += wxString::FromUTF8(qname);
1421   free(qname);
1422   sql += wxT("\", \"");
1423   strcpy(xsql, xmlColumn.ToUTF8());
1424   qname = gaiaDoubleQuotedSql(xsql);
1425   sql += wxString::FromUTF8(qname);
1426   free(qname);
1427   if (inPathColumn.Len() > 0)
1428     {
1429       // appending the InPath column
1430       sql += wxT("\", \"");
1431       strcpy(xsql, inPathColumn.ToUTF8());
1432       qname = gaiaDoubleQuotedSql(xsql);
1433       sql += wxString::FromUTF8(qname);
1434       free(qname);
1435     }
1436   if (schemaUriColumn.Len() > 0)
1437     {
1438       // appending the SchemaURI column
1439       sql += wxT("\", \"");
1440       strcpy(xsql, schemaUriColumn.ToUTF8());
1441       qname = gaiaDoubleQuotedSql(xsql);
1442       sql += wxString::FromUTF8(qname);
1443       free(qname);
1444     }
1445   if (parseErrColumn.Len() > 0)
1446     {
1447       // appending the ParseError column
1448       sql += wxT("\", \"");
1449       strcpy(xsql, parseErrColumn.ToUTF8());
1450       qname = gaiaDoubleQuotedSql(xsql);
1451       sql += wxString::FromUTF8(qname);
1452       free(qname);
1453     }
1454   if (validateErrColumn.Len() > 0)
1455     {
1456       // appending the ValidateError column
1457       sql += wxT("\", \"");
1458       strcpy(xsql, validateErrColumn.ToUTF8());
1459       qname = gaiaDoubleQuotedSql(xsql);
1460       sql += wxString::FromUTF8(qname);
1461       free(qname);
1462     }
1463   sql += wxT("\") VALUES (NULL, ?");
1464   if (inPathColumn.Len() > 0)
1465     sql += wxT(", ?");
1466   if (schemaUriColumn.Len() > 0)
1467     sql += wxT(", ?");
1468   if (parseErrColumn.Len() > 0)
1469     sql += wxT(", ?");
1470   if (validateErrColumn.Len() > 0)
1471     sql += wxT(", ?");
1472   sql += wxT(")");
1473   ret = sqlite3_prepare_v2(SqliteHandle, sql.ToUTF8(), sql.Len(), &stmt, NULL);
1474   if (ret != SQLITE_OK)
1475     {
1476       wxMessageBox(wxT("INSERT INTO XML target table error: ") +
1477                    wxString::FromUTF8(sqlite3_errmsg(SqliteHandle)),
1478                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
1479       return;
1480     }
1481 // stating a transaction
1482   ret = sqlite3_exec(SqliteHandle, "BEGIN", NULL, NULL, &errMsg);
1483   if (ret != SQLITE_OK)
1484     {
1485       wxMessageBox(wxT("BEGIN error: ") + wxString::FromUTF8(errMsg),
1486                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
1487       sqlite3_free(errMsg);
1488     }
1489 
1490   if (folder == true)
1491     cnt =
1492       XmlDocumentLoadDir(path, suffix, compressed, schemaURI,
1493                          isInternalSchemaUri, inPathColumn, parseErrColumn,
1494                          validateErrColumn, schemaUriColumn, stmt, &failed);
1495   else
1496     cnt =
1497       XmlDocumentLoadFile(path, compressed, schemaURI, isInternalSchemaUri,
1498                           inPathColumn, schemaUriColumn, parseErrColumn,
1499                           validateErrColumn, stmt, &failed);
1500 
1501 // commits the transaction
1502   ret = sqlite3_exec(SqliteHandle, "COMMIT", NULL, NULL, &errMsg);
1503   if (ret != SQLITE_OK)
1504     {
1505       wxMessageBox(wxT("COMMIT error: ") + wxString::FromUTF8(errMsg),
1506                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
1507       sqlite3_free(errMsg);
1508     }
1509   sqlite3_finalize(stmt);
1510   sprintf(msg, "%d XML Document%s processed\n\n", cnt,
1511           (cnt > 1) ? "s were" : " was");
1512   wxString message = wxString::FromUTF8(msg);
1513   sprintf(msg, "Valid XMLDocuments: %d\n", cnt - failed);
1514   message += wxString::FromUTF8(msg);
1515   sprintf(msg, "Failures: %d\n", failed);
1516   message += wxString::FromUTF8(msg);
1517   wxMessageBox(message, wxT("spatialite_gui"), wxOK | wxICON_INFORMATION, this);
1518 }
1519 
InsertIntoXmlTable(sqlite3_stmt * stmt,char * blob,int sz,wxString & inPathColumn,wxString & path,wxString & schemaUriColumn,const char * schemaUri,wxString & parseErrColumn,const char * parseError,wxString & validateErrColumn,const char * validateError)1520 bool MyFrame::InsertIntoXmlTable(sqlite3_stmt * stmt, char *blob,
1521                                  int sz, wxString & inPathColumn,
1522                                  wxString & path, wxString & schemaUriColumn,
1523                                  const char *schemaUri,
1524                                  wxString & parseErrColumn,
1525                                  const char *parseError,
1526                                  wxString & validateErrColumn,
1527                                  const char *validateError)
1528 {
1529 //
1530 // attemping to insert into the XML target table
1531 //
1532   int ret;
1533   int i_col = 2;
1534   sqlite3_reset(stmt);
1535   sqlite3_clear_bindings(stmt);
1536   sqlite3_bind_blob(stmt, 1, blob, sz, free);
1537   if (inPathColumn.Len() > 0)
1538     {
1539       // binding the InPath value
1540       char x_path[1024];
1541       wxFileName fn = wxFileName(path);
1542       wxString name = fn.GetName();
1543       if (fn.GetExt().Len() > 0)
1544         name += wxT(".") + fn.GetExt();
1545       strcpy(x_path, name.ToUTF8());
1546       sqlite3_bind_text(stmt, i_col++, x_path, strlen(x_path),
1547                         SQLITE_TRANSIENT);
1548     }
1549   if (schemaUriColumn.Len() > 0)
1550     {
1551       // binding the SchemaURI value
1552       if (schemaUri == NULL)
1553         sqlite3_bind_null(stmt, i_col++);
1554       else
1555         sqlite3_bind_text(stmt, i_col++, schemaUri, strlen(schemaUri),
1556                           SQLITE_STATIC);
1557     }
1558   if (parseErrColumn.Len() > 0)
1559     {
1560       // binding the ParseError value
1561       if (parseError == NULL)
1562         sqlite3_bind_null(stmt, i_col++);
1563       else
1564         sqlite3_bind_text(stmt, i_col++, parseError, strlen(parseError),
1565                           SQLITE_STATIC);
1566     }
1567   if (validateErrColumn.Len() > 0)
1568     {
1569       // binding the ValidateError value
1570       if (validateError == NULL)
1571         sqlite3_bind_null(stmt, i_col++);
1572       else
1573         sqlite3_bind_text(stmt, i_col++, validateError, strlen(validateError),
1574                           SQLITE_STATIC);
1575     }
1576   ret = sqlite3_step(stmt);
1577   if (ret == SQLITE_DONE || ret == SQLITE_ROW)
1578     return true;
1579   wxMessageBox(wxT("XML-INSERT: sqlite3_step() error: ") +
1580                wxString::FromUTF8(sqlite3_errmsg(SqliteHandle)),
1581                wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
1582   return false;
1583 }
1584 
CheckOrCreateXmlTable(wxString & table,wxString & pkName,wxString & xmlColumn,wxString & inPathColumn,wxString & schemaUriColumn,wxString & parseErrColumn,wxString & validateErrColumn)1585 bool MyFrame::CheckOrCreateXmlTable(wxString & table, wxString & pkName,
1586                                     wxString & xmlColumn,
1587                                     wxString & inPathColumn,
1588                                     wxString & schemaUriColumn,
1589                                     wxString & parseErrColumn,
1590                                     wxString & validateErrColumn)
1591 {
1592 //
1593 // creates the XML DB table / or checks an existing one for validity
1594 //
1595   int ret;
1596   wxString sql;
1597   char *errMsg;
1598   char xsql[8192];
1599   char *qname;
1600   bool ok_xmlblob = false;
1601   bool ok_inPath = false;
1602   bool ok_schemaURI = false;
1603   bool ok_parseErr = false;
1604   bool ok_validateErr = false;
1605   const char *name;
1606   int i;
1607   char **results;
1608   int rows;
1609   int columns;
1610   sql = wxT("CREATE TABLE IF NOT EXISTS \"");
1611   strcpy(xsql, table.ToUTF8());
1612   qname = gaiaDoubleQuotedSql(xsql);
1613   sql += wxString::FromUTF8(qname);
1614   free(qname);
1615   sql += wxT("\" (\n\"");
1616   strcpy(xsql, pkName.ToUTF8());
1617   qname = gaiaDoubleQuotedSql(xsql);
1618   sql += wxString::FromUTF8(qname);
1619   free(qname);
1620   sql += wxT("\" INTEGER PRIMARY KEY AUTOINCREMENT,\n\"");
1621   strcpy(xsql, xmlColumn.ToUTF8());
1622   qname = gaiaDoubleQuotedSql(xsql);
1623   sql += wxString::FromUTF8(qname);
1624   free(qname);
1625   sql += wxT("\" BLOB NOT NULL");
1626   if (inPathColumn.Len() > 0)
1627     {
1628       // adding the InPath Column
1629       sql += wxT("\n,\"");
1630       strcpy(xsql, inPathColumn.ToUTF8());
1631       qname = gaiaDoubleQuotedSql(xsql);
1632       sql += wxString::FromUTF8(qname);
1633       free(qname);
1634       sql += wxT("\" TEXT NOT NULL");
1635     }
1636   if (schemaUriColumn.Len() > 0)
1637     {
1638       // adding the SchemaURI Column
1639       sql += wxT("\n,\"");
1640       strcpy(xsql, schemaUriColumn.ToUTF8());
1641       qname = gaiaDoubleQuotedSql(xsql);
1642       sql += wxString::FromUTF8(qname);
1643       free(qname);
1644       sql += wxT("\" TEXT");
1645     }
1646   if (parseErrColumn.Len() > 0)
1647     {
1648       // adding the ParseError Column
1649       sql += wxT("\n,\"");
1650       strcpy(xsql, parseErrColumn.ToUTF8());
1651       qname = gaiaDoubleQuotedSql(xsql);
1652       sql += wxString::FromUTF8(qname);
1653       free(qname);
1654       sql += wxT("\" TEXT");
1655     }
1656   if (validateErrColumn.Len() > 0)
1657     {
1658       // adding the validateError Column
1659       sql += wxT("\n,\"");
1660       strcpy(xsql, validateErrColumn.ToUTF8());
1661       qname = gaiaDoubleQuotedSql(xsql);
1662       sql += wxString::FromUTF8(qname);
1663       free(qname);
1664       sql += wxT("\" TEXT");
1665     }
1666   sql += wxT(")");
1667   ret = sqlite3_exec(SqliteHandle, sql.ToUTF8(), NULL, NULL, &errMsg);
1668   if (ret != SQLITE_OK)
1669     {
1670       wxMessageBox(wxT("CREATE XML Target Table error: ") +
1671                    wxString::FromUTF8(errMsg), wxT("spatialite_gui"),
1672                    wxOK | wxICON_ERROR, this);
1673       sqlite3_free(errMsg);
1674       return false;
1675     }
1676 
1677   sql = wxT("PRAGMA table_info(\"");
1678   strcpy(xsql, table.ToUTF8());
1679   qname = gaiaDoubleQuotedSql(xsql);
1680   sql += wxString::FromUTF8(qname);
1681   free(qname);
1682   sql += wxT("\")");
1683   ret =
1684     sqlite3_get_table(SqliteHandle, sql.ToUTF8(), &results, &rows, &columns,
1685                       &errMsg);
1686   if (ret != SQLITE_OK)
1687     {
1688       wxMessageBox(wxT("PRAGMA table_info(xmlTargetTable) error: ") +
1689                    wxString::FromUTF8(errMsg), wxT("spatialite_gui"),
1690                    wxOK | wxICON_ERROR, this);
1691       sqlite3_free(errMsg);
1692       goto abort;
1693     }
1694   if (rows < 1)
1695     ;
1696   else
1697     {
1698       strcpy(xsql, xmlColumn.ToUTF8());
1699       for (i = 1; i <= rows; i++)
1700         {
1701           name = results[(i * columns) + 1];
1702           if (strcasecmp(name, xsql) == 0)
1703             ok_xmlblob = true;
1704         }
1705       if (schemaUriColumn.Len() == 0)
1706         ok_schemaURI = true;
1707       else
1708         {
1709           strcpy(xsql, schemaUriColumn.ToUTF8());
1710           for (i = 1; i <= rows; i++)
1711             {
1712               name = results[(i * columns) + 1];
1713               if (strcasecmp(name, xsql) == 0)
1714                 ok_schemaURI = true;
1715             }
1716         }
1717       if (inPathColumn.Len() == 0)
1718         ok_inPath = true;
1719       else
1720         {
1721           strcpy(xsql, inPathColumn.ToUTF8());
1722           for (i = 1; i <= rows; i++)
1723             {
1724               name = results[(i * columns) + 1];
1725               if (strcasecmp(name, xsql) == 0)
1726                 ok_inPath = true;
1727             }
1728         }
1729       if (parseErrColumn.Len() == 0)
1730         ok_parseErr = true;
1731       else
1732         {
1733           strcpy(xsql, parseErrColumn.ToUTF8());
1734           for (i = 1; i <= rows; i++)
1735             {
1736               name = results[(i * columns) + 1];
1737               if (strcasecmp(name, xsql) == 0)
1738                 ok_parseErr = true;
1739             }
1740         }
1741       if (validateErrColumn.Len() == 0)
1742         ok_validateErr = true;
1743       else
1744         {
1745           strcpy(xsql, validateErrColumn.ToUTF8());
1746           for (i = 1; i <= rows; i++)
1747             {
1748               name = results[(i * columns) + 1];
1749               if (strcasecmp(name, xsql) == 0)
1750                 ok_validateErr = true;
1751             }
1752         }
1753     }
1754   sqlite3_free_table(results);
1755   if (ok_xmlblob == true && ok_inPath == true && ok_schemaURI == true
1756       && ok_parseErr == true && ok_validateErr == true)
1757     ;
1758   else
1759     {
1760       wxMessageBox(wxT
1761                    ("ERROR: XML target table already exists, but has incompatible columns"),
1762                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
1763       sqlite3_free(errMsg);
1764       goto abort;
1765     }
1766   return true;
1767 abort:
1768   return false;
1769 }
1770 
XmlDocumentLoadDir(wxString & path,wxString & suffix,int compressed,const char * schemaURI,bool isInternalSchemaUri,wxString & inPathColumn,wxString & schemaUriColumn,wxString & parseErrColumn,wxString & validateErrColumn,sqlite3_stmt * stmt,int * failed)1771 int MyFrame::XmlDocumentLoadDir(wxString & path, wxString & suffix,
1772                                 int compressed, const char *schemaURI,
1773                                 bool isInternalSchemaUri,
1774                                 wxString & inPathColumn,
1775                                 wxString & schemaUriColumn,
1776                                 wxString & parseErrColumn,
1777                                 wxString & validateErrColumn,
1778                                 sqlite3_stmt * stmt, int *failed)
1779 {
1780 //
1781 // importing XML Document files from a whole DIRECTORY
1782 //
1783   int fails;
1784   *failed = 0;
1785 #if defined(_WIN32) && !defined(__MINGW32__)
1786 /* Visual Studio .NET */
1787   struct _finddata_t c_file;
1788   intptr_t hFile;
1789   int cnt = 0;
1790   wxString filePath;
1791   if (_chdir(path.ToUTF8()) < 0)
1792     return 0;
1793   if ((hFile = _findfirst("*.*", &c_file)) == -1L)
1794     ;
1795   else
1796     {
1797       while (1)
1798         {
1799           if ((c_file.attrib & _A_RDONLY) == _A_RDONLY
1800               || (c_file.attrib & _A_NORMAL) == _A_NORMAL)
1801             {
1802               if (IsValidSuffix(c_file.name, suffix))
1803                 {
1804                   filePath = path;
1805                   filePath += wxT("/") + wxString::FromUTF8(c_file.name);
1806                   cnt +=
1807                     XmlDocumentLoadFile(filePath, compressed, schemaURI,
1808                                         isInternalSchemaUri, inPathColumn,
1809                                         schemaUriColumn, parseErrColumn,
1810                                         validateErrColumn, stmt, &fails);
1811                   *failed += fails;
1812                 }
1813             }
1814           if (_findnext(hFile, &c_file) != 0)
1815             break;
1816         };
1817       _findclose(hFile);
1818     }
1819   return cnt;
1820 #else
1821 /* not Visual Studio .NET */
1822   int cnt = 0;
1823   wxString filePath;
1824   struct dirent *entry;
1825   DIR *dir = opendir(path.ToUTF8());
1826   if (!dir)
1827     return 0;
1828   while (1)
1829     {
1830       // scanning dir-entries
1831       entry = readdir(dir);
1832       if (!entry)
1833         break;
1834       if (IsValidSuffix(entry->d_name, suffix))
1835         {
1836           filePath = path;
1837           filePath += wxT("/") + wxString::FromUTF8(entry->d_name);
1838           cnt +=
1839             XmlDocumentLoadFile(filePath, compressed, schemaURI,
1840                                 isInternalSchemaUri, inPathColumn,
1841                                 schemaUriColumn, parseErrColumn,
1842                                 validateErrColumn, stmt, &fails);
1843           *failed += fails;
1844         }
1845     }
1846   closedir(dir);
1847   return cnt;
1848 #endif
1849 }
1850 
IsValidSuffix(const char * fileName,wxString & suffix)1851 bool MyFrame::IsValidSuffix(const char *fileName, wxString & suffix)
1852 {
1853 // testing if a FileName ends with the expected suffix
1854   if (suffix.Len() == 0)
1855     return true;
1856 
1857   char suf[1024];
1858   strcpy(suf, suffix.ToUTF8());
1859   int len1 = strlen(fileName);
1860   int len2 = strlen(suf);
1861   int off = len1 - len2;
1862   if (off >= 1)
1863     {
1864       if (strcasecmp(fileName + off, suf) == 0)
1865         return true;
1866     }
1867   return false;
1868 }
1869 
XmlDocumentLoadFile(wxString & path,int compressed,const char * schemaURI,bool isInternalSchemaUri,wxString & inPathColumn,wxString & schemaUriColumn,wxString & parseErrColumn,wxString & validateErrColumn,sqlite3_stmt * stmt,int * failed)1870 int MyFrame::XmlDocumentLoadFile(wxString & path, int compressed,
1871                                  const char *schemaURI,
1872                                  bool isInternalSchemaUri,
1873                                  wxString & inPathColumn,
1874                                  wxString & schemaUriColumn,
1875                                  wxString & parseErrColumn,
1876                                  wxString & validateErrColumn,
1877                                  sqlite3_stmt * stmt, int *failed)
1878 {
1879 //
1880 // importing a single XML Document file
1881 //
1882 #ifdef ENABLE_LIBXML2           /* only if LIBXML2 is enabled */
1883   FILE *fl;
1884   int sz = 0;
1885   int rd;
1886   int loaded = 0;
1887   unsigned char *blob = NULL;
1888   char *xml = NULL;
1889   int xml_size;
1890   char *parseError = NULL;
1891   char *validateError = NULL;
1892   char *p_schemaURI = NULL;
1893   int len;
1894   *failed = 0;
1895 
1896   fl = fopen(path.ToUTF8(), "rb");
1897   if (!fl)
1898     return 0;
1899   if (fseek(fl, 0, SEEK_END) == 0)
1900     sz = ftell(fl);
1901   blob = (unsigned char *) malloc(sz);
1902   rewind(fl);
1903   rd = fread(blob, 1, sz, fl);
1904   if (rd == sz)
1905     {
1906       // attempting to parse (and possibly validate) the XMLDocument
1907       if (isInternalSchemaUri)
1908         {
1909           // attempting to retrieve an internally defined SchemaURI
1910           char *internalSchemaURI =
1911             gaiaXmlGetInternalSchemaURI(InternalCache, blob, rd);
1912           if (internalSchemaURI == NULL)
1913             {
1914               // unable to identify the SchemaURI
1915               xml = NULL;
1916           } else
1917             {
1918               // ok, attempting to validate using the internal SchemaURI
1919               len = strlen(internalSchemaURI);
1920               p_schemaURI = (char *) malloc(len + 1);
1921               strcpy(p_schemaURI, internalSchemaURI);
1922               gaiaXmlToBlob(InternalCache, blob, rd, compressed,
1923                             internalSchemaURI, (unsigned char **) (&xml),
1924                             &xml_size, &parseError, &validateError);
1925               free(internalSchemaURI);
1926             }
1927       } else
1928         {
1929           // possibly validating against the externally defined SchemaURI
1930           if (schemaURI)
1931             {
1932               len = strlen(schemaURI);
1933               p_schemaURI = (char *) malloc(len + 1);
1934               strcpy(p_schemaURI, schemaURI);
1935             }
1936           gaiaXmlToBlob(InternalCache, blob, rd, compressed, schemaURI,
1937                         (unsigned char **) (&xml), &xml_size, &parseError,
1938                         &validateError);
1939         }
1940       if (xml == NULL)
1941         {
1942           /* creating an empty BLOB as a placeholder */
1943           xml_size = 1;
1944           xml = (char *) malloc(xml_size);
1945           *xml = '\0';
1946           *failed = 1;
1947         }
1948       if (InsertIntoXmlTable
1949           (stmt, xml, xml_size, inPathColumn, path, schemaUriColumn,
1950            p_schemaURI, parseErrColumn, parseError, validateErrColumn,
1951            validateError) == false)
1952         goto stop;
1953       loaded = 1;
1954     }
1955 stop:
1956   if (p_schemaURI)
1957     free(p_schemaURI);
1958   if (blob)
1959     free(blob);
1960   fclose(fl);
1961   return loaded;
1962 
1963 #else
1964 
1965   wxMessageBox(wxT
1966                ("Sorry, spatialite_gui was built disabling LIBXML2\n\nUnsupported operation"),
1967                wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
1968 
1969 #endif /* end LIBXML2 conditionals */
1970 }
1971 
ImportDXFfiles(wxString & path,bool folder,wxString & prefix,wxString & layer,int srid,bool force2d,bool force3d,bool mixed,bool linked,bool unlinked,bool append)1972 void MyFrame::ImportDXFfiles(wxString & path, bool folder, wxString & prefix,
1973                              wxString & layer, int srid, bool force2d,
1974                              bool force3d, bool mixed, bool linked,
1975                              bool unlinked, bool append)
1976 {
1977 //
1978 // trying to import DXF drawing files
1979 //
1980   int cnt;
1981   int failed;
1982   char msg[256];
1983   if (folder == true)
1984     cnt =
1985       DxfLoadDir(path, prefix, layer, srid, force2d, force3d, mixed, linked,
1986                  unlinked, append, &failed);
1987   else
1988     cnt =
1989       DxfLoadFile(path, prefix, layer, srid, force2d, force3d, mixed, linked,
1990                   unlinked, append, &failed);
1991   wxString message = wxString::FromUTF8(msg);
1992   sprintf(msg, "Imported DXF files: %d\n", cnt - failed);
1993   message += wxString::FromUTF8(msg);
1994   sprintf(msg, "Failures: %d\n", failed);
1995   message += wxString::FromUTF8(msg);
1996   wxMessageBox(message, wxT("spatialite_gui"), wxOK | wxICON_INFORMATION, this);
1997 }
1998 
DxfLoadDir(wxString & path,wxString & prefix,wxString & layer,int srid,bool force2d,bool force3d,bool mixed,bool linked,bool unlinked,bool append,int * failed)1999 int MyFrame::DxfLoadDir(wxString & path, wxString & prefix, wxString & layer,
2000                         int srid, bool force2d, bool force3d, bool mixed,
2001                         bool linked, bool unlinked, bool append, int *failed)
2002 {
2003 //
2004 // importing DXF files from a whole DIRECTORY
2005 //
2006   wxString suffix = wxT(".dxf");
2007   int fails;
2008   *failed = 0;
2009 #if defined(_WIN32) && !defined(__MINGW32__)
2010 /* Visual Studio .NET */
2011   struct _finddata_t c_file;
2012   intptr_t hFile;
2013   int cnt = 0;
2014   wxString filePath;
2015   if (_chdir(path.ToUTF8()) < 0)
2016     return 0;
2017   if ((hFile = _findfirst("*.*", &c_file)) == -1L)
2018     ;
2019   else
2020     {
2021       while (1)
2022         {
2023           if ((c_file.attrib & _A_RDONLY) == _A_RDONLY
2024               || (c_file.attrib & _A_NORMAL) == _A_NORMAL)
2025             {
2026               if (IsValidSuffix(entry->d_name, suffix))
2027                 {
2028                   filePath = path;
2029                   filePath += wxT("/") + wxString::FromUTF8(c_file.name);
2030                   cnt +=
2031                     DxfLoadFile(filePath, prefix, layer, srid, force2d, force3d,
2032                                 mixed, linked, unlinked, append, &fails);
2033                   *failed += fails;
2034                 }
2035             }
2036           if (_findnext(hFile, &c_file) != 0)
2037             break;
2038         };
2039       _findclose(hFile);
2040     }
2041   return cnt;
2042 #else
2043 /* not Visual Studio .NET */
2044   int cnt = 0;
2045   wxString filePath;
2046   struct dirent *entry;
2047   DIR *dir = opendir(path.ToUTF8());
2048   if (!dir)
2049     return 0;
2050   while (1)
2051     {
2052       // scanning dir-entries
2053       entry = readdir(dir);
2054       if (!entry)
2055         break;
2056       if (IsValidSuffix(entry->d_name, suffix))
2057         {
2058           filePath = path;
2059           filePath += wxT("/") + wxString::FromUTF8(entry->d_name);
2060           cnt +=
2061             DxfLoadFile(filePath, prefix, layer, srid, force2d, force3d, mixed,
2062                         linked, unlinked, append, &fails);
2063           *failed += fails;
2064         }
2065     }
2066   closedir(dir);
2067   return cnt;
2068 #endif
2069 }
2070 
DxfLoadFile(wxString & path,wxString & prefix,wxString & layer,int srid,bool force2d,bool force3d,bool mixed,bool linked,bool unlinked,bool append,int * failed)2071 int MyFrame::DxfLoadFile(wxString & path, wxString & prefix, wxString & layer,
2072                          int srid, bool force2d, bool force3d, bool mixed,
2073                          bool linked, bool unlinked, bool append, int *failed)
2074 {
2075 //
2076 // importing a single DXF file
2077 //
2078   int force_dims = GAIA_DXF_AUTO_2D_3D;
2079   int special_rings = GAIA_DXF_RING_NONE;
2080   char dxf_path[1024];
2081   char xprefix[1024];
2082   const char *xxprefix = NULL;
2083   char selected_layer[1024];
2084   const char *xselected_layer = NULL;
2085   gaiaDxfParserPtr dxf;
2086   bool error = false;
2087 
2088   *failed = 0;
2089 // creating a DXF parser
2090   if (prefix.Len() > 0)
2091     {
2092       strcpy(xprefix, prefix.ToUTF8());
2093       xxprefix = xprefix;
2094     }
2095   if (layer.Len() > 0)
2096     {
2097       strcpy(selected_layer, layer.ToUTF8());
2098       xselected_layer = selected_layer;
2099     }
2100   if (force2d)
2101     force_dims = GAIA_DXF_FORCE_2D;
2102   else if (force3d)
2103     force_dims = GAIA_DXF_FORCE_3D;
2104   if (linked)
2105     special_rings = GAIA_DXF_RING_LINKED;
2106   else if (unlinked)
2107     special_rings = GAIA_DXF_RING_UNLINKED;
2108   dxf =
2109     gaiaCreateDxfParser(srid, force_dims, xxprefix, xselected_layer,
2110                         special_rings);
2111   if (dxf == NULL)
2112     {
2113       *failed = 1;
2114       goto stop;
2115     }
2116 // attempting to parse the DXF input file
2117   strcpy(dxf_path, path.ToUTF8());
2118   if (gaiaParseDxfFile(dxf, dxf_path))
2119     {
2120 // loading into the DB
2121       int mode = GAIA_DXF_IMPORT_BY_LAYER;
2122       if (mixed)
2123         mode = GAIA_DXF_IMPORT_MIXED;
2124       if (!gaiaLoadFromDxfParser(GetSqlite(), dxf, mode, append))
2125         {
2126           wxMessageBox(wxT("DB error while loading: ") + path,
2127                        wxT("spatialite_gui"), wxOK | wxICON_ERROR, this);
2128           *failed = 1;
2129         }
2130   } else
2131     {
2132       wxMessageBox(wxT("Unable to parse: ") + path, wxT("spatialite_gui"),
2133                    wxOK | wxICON_ERROR, this);
2134       *failed = 1;
2135     }
2136 
2137 
2138 stop:
2139 // destroying the DXF parser
2140   gaiaDestroyDxfParser(dxf);
2141   return 1;
2142 }
2143