summaryrefslogtreecommitdiffstats
path: root/parse-xml.c
diff options
context:
space:
mode:
Diffstat (limited to 'parse-xml.c')
-rw-r--r--parse-xml.c445
1 files changed, 349 insertions, 96 deletions
diff --git a/parse-xml.c b/parse-xml.c
index 9f1e64a0e..c5ed21a54 100644
--- a/parse-xml.c
+++ b/parse-xml.c
@@ -21,6 +21,10 @@
int verbose, quit;
int metric = 1;
+int last_xml_version = -1;
+bool abort_read_of_old_file = false;
+bool v2_question_shown = false;
+bool imported_via_xslt = false;
static xmlDoc *test_xslt_transforms(xmlDoc *doc, const char **params);
@@ -128,6 +132,7 @@ const struct units IMPERIAL_units = IMPERIAL_UNITS;
#define MAX_EVENT_NAME 128
static struct divecomputer *cur_dc;
static struct dive *cur_dive;
+static struct dive_site *cur_dive_site;
static dive_trip_t *cur_trip = NULL;
static struct sample *cur_sample;
static struct picture *cur_picture;
@@ -746,6 +751,9 @@ static void try_to_match_autogroup(const char *name, char *buf)
void add_gas_switch_event(struct dive *dive, struct divecomputer *dc, int seconds, int idx)
{
+ /* sanity check so we don't crash */
+ if (idx < 0 || idx >= MAX_CYLINDERS)
+ return;
/* The gas switch event format is insane for historical reasons */
struct gasmix *mix = &dive->cylinder[idx].gasmix;
int o2 = get_o2(mix);
@@ -933,10 +941,8 @@ static void try_to_fill_sample(struct sample *sample, const char *name, char *bu
return;
if (MATCH("sensor3.sample", double_to_o2pressure, &sample->o2sensor[2])) // up to 3 CCR sensors
return;
- if (MATCH("po2.sample", double_to_o2pressure, &sample->setpoint)) {
- cur_dive->dc.divemode = CCR;
+ if (MATCH("po2.sample", double_to_o2pressure, &sample->setpoint))
return;
- }
if (MATCH("heartbeat", get_uint8, &sample->heartbeat))
return;
if (MATCH("bearing", get_bearing, &sample->bearing))
@@ -968,22 +974,20 @@ void try_to_fill_userid(const char *name, char *buf)
static const char *country, *city;
-static void divinglog_place(char *place, char **location)
+static void divinglog_place(char *place, uint32_t *uuid)
{
- char buffer[1024], *p;
- int len;
+ char buffer[1024];
- len = snprintf(buffer, sizeof(buffer),
- "%s%s%s%s%s",
- place,
- city ? ", " : "",
- city ? city : "",
- country ? ", " : "",
- country ? country : "");
-
- p = malloc(len + 1);
- memcpy(p, buffer, len + 1);
- *location = p;
+ snprintf(buffer, sizeof(buffer),
+ "%s%s%s%s%s",
+ place,
+ city ? ", " : "",
+ city ? city : "",
+ country ? ", " : "",
+ country ? country : "");
+ *uuid = get_dive_site_uuid_by_name(buffer, NULL);
+ if (*uuid == 0)
+ *uuid = create_dive_site(buffer);
city = NULL;
country = NULL;
@@ -1005,7 +1009,7 @@ static int divinglog_dive_match(struct dive *dive, const char *name, char *buf)
MATCH("names.buddy", utf8_string, &dive->buddy) ||
MATCH("name.country", utf8_string, &country) ||
MATCH("name.city", utf8_string, &city) ||
- MATCH("name.place", divinglog_place, &dive->location) ||
+ MATCH("name.place", divinglog_place, &dive->dive_site_uuid) ||
0;
}
@@ -1127,23 +1131,119 @@ degrees_t parse_degrees(char *buf, char **end)
static void gps_lat(char *buffer, struct dive *dive)
{
char *end;
-
- dive->latitude = parse_degrees(buffer, &end);
+ degrees_t latitude = parse_degrees(buffer, &end);
+ struct dive_site *ds = get_dive_site_for_dive(dive);
+ if (!ds) {
+ dive->dive_site_uuid = create_dive_site_with_gps(NULL, latitude, (degrees_t){0});
+ } else {
+ if (ds->latitude.udeg && ds->latitude.udeg != latitude.udeg)
+ fprintf(stderr, "Oops, changing the latitude of existing dive site id %8x name %s; not good\n", ds->uuid, ds->name ?: "(unknown)");
+ ds->latitude = latitude;
+ }
}
static void gps_long(char *buffer, struct dive *dive)
{
char *end;
+ degrees_t longitude = parse_degrees(buffer, &end);
+ struct dive_site *ds = get_dive_site_for_dive(dive);
+ if (!ds) {
+ dive->dive_site_uuid = create_dive_site_with_gps(NULL, (degrees_t){0}, longitude);
+ } else {
+ if (ds->longitude.udeg && ds->longitude.udeg != longitude.udeg)
+ fprintf(stderr, "Oops, changing the longitude of existing dive site id %8x name %s; not good\n", ds->uuid, ds->name ?: "(unknown)");
+ ds->longitude = longitude;
+ }
- dive->longitude = parse_degrees(buffer, &end);
}
-static void gps_location(char *buffer, struct dive *dive)
+static void gps_location(char *buffer, struct dive_site *ds)
{
char *end;
- dive->latitude = parse_degrees(buffer, &end);
- dive->longitude = parse_degrees(end, &end);
+ ds->latitude = parse_degrees(buffer, &end);
+ ds->longitude = parse_degrees(end, &end);
+}
+
+/* this is in qthelper.cpp, so including the .h file is a pain */
+extern const char *printGPSCoords(int lat, int lon);
+extern void add_geo_information_for_loockup(degrees_t latitude, degrees_t longitude, uint32_t uuid);
+
+static void gps_in_dive(char *buffer, struct dive *dive)
+{
+ char *end;
+ struct dive_site *ds = NULL;
+ degrees_t latitude = parse_degrees(buffer, &end);
+ degrees_t longitude = parse_degrees(end, &end);
+ fprintf(stderr, "got lat %f lon %f\n", latitude.udeg / 1000000.0, longitude.udeg / 1000000.0);
+ uint32_t uuid = dive->dive_site_uuid;
+ if (uuid == 0) {
+ uuid = get_dive_site_uuid_by_gps(latitude, longitude, &ds);
+ if (ds) {
+ fprintf(stderr, "found dive site {%s} with these coordinates\n", ds->name);
+ dive->dive_site_uuid = uuid;
+ } else {
+ fprintf(stderr, "found no uuid in dive, no existing dive site with these coordinates, creating a new divesite without name and above GPS\n");
+ dive->dive_site_uuid = create_dive_site_with_gps("", latitude, longitude);
+ ds = get_dive_site_by_uuid(dive->dive_site_uuid);
+ }
+ } else {
+ fprintf(stderr, "found uuid in dive, checking to see if we should add GPS\n");
+ ds = get_dive_site_by_uuid(uuid);
+ if (dive_site_has_gps_location(ds) &&
+ (latitude.udeg != 0 || longitude.udeg != 0) &&
+ (ds->latitude.udeg != latitude.udeg || ds->longitude.udeg != longitude.udeg)) {
+ // Houston, we have a problem
+ fprintf(stderr, "dive site uuid in dive, but gps location (%10.6f/%10.6f) different from dive location (%10.6f/%10.6f)\n",
+ ds->latitude.udeg / 1000000.0, ds->longitude.udeg / 1000000.0,
+ latitude.udeg / 1000000.0, longitude.udeg / 1000000.0);
+ ds->notes = add_to_string(ds->notes, translate("gettextFromC", "multiple gps locations for this dive site; also %s\n"),
+ printGPSCoords(latitude.udeg, longitude.udeg));
+ } else {
+ fprintf(stderr, "let's add the gps coordinates to divesite with uuid %8x and name %s\n", ds->uuid, ds->name ?: "(none)");
+ ds->latitude = latitude;
+ ds->longitude = longitude;
+ }
+ }
+ if (ds && (!ds->notes || strstr(ds->notes, "countrytag:") == NULL))
+ add_geo_information_for_loockup(latitude, longitude, dive->dive_site_uuid);
+}
+
+static void add_dive_site(char *buffer, struct dive *dive)
+{
+ fprintf(stderr, "add_dive_site with name %s\n", buffer);
+ int size = trimspace(buffer);
+ if(size) {
+ uint32_t uuid = dive->dive_site_uuid;
+ struct dive_site *ds = get_dive_site_by_uuid(uuid);
+ if (uuid && !ds) {
+ // that's strange - we have a uuid but it doesn't exist - let's just ignore it
+ fprintf(stderr, "dive contains a non-existing dive site uuid %x\n", dive->dive_site_uuid);
+ uuid = 0;
+ }
+ if (!uuid)
+ // if the dive doesn't have a uuid, check if there's already a dive site by this name
+ uuid = get_dive_site_uuid_by_name(buffer, &ds);
+ if (ds) {
+ // we have a uuid, let's hope there isn't a different name
+ fprintf(stderr, "have existing site with name {%s} gps %f/%f ", ds->name, ds->latitude.udeg / 1000000.0, ds->longitude.udeg / 1000000.0);
+ if (same_string(ds->name, "")) {
+ fprintf(stderr, "so now add name {%s}\n", buffer);
+ ds->name = copy_string(buffer);
+ } else if (!same_string(ds->name, buffer)) {
+ // coin toss, let's just keep the first name we found and add the new one to the notes
+ fprintf(stderr, "which means the dive already links to dive site of different name {%s} / {%s}\n", ds->name, buffer);
+ ds->notes = add_to_string(ds->notes, translate("gettextFromC", "additional name for site: %s\n"), buffer);
+ } else {
+ // add the existing dive site to the current dive
+ fprintf(stderr, "we have an existing location, using {%s}\n", ds->name);
+ dive->dive_site_uuid = uuid;
+ }
+ } else {
+ fprintf(stderr, "no uuid, create new dive site with name {%s}\n", buffer);
+ dive->dive_site_uuid = create_dive_site(buffer);
+ }
+ }
}
static void gps_picture_location(char *buffer, struct picture *pic)
@@ -1173,7 +1273,8 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf)
default:
break;
}
-
+ if (MATCH("divesiteid", hex_value, &dive->dive_site_uuid))
+ return;
if (MATCH("number", get_index, &dive->number))
return;
if (MATCH("tags", divetags, &dive->tag_list))
@@ -1199,13 +1300,15 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf)
return;
if (MATCH("gps.picture", gps_picture_location, cur_picture))
return;
+ if (MATCH("hash.picture", utf8_string, &cur_picture->hash))
+ return;
if (MATCH("cylinderstartpressure", pressure, &dive->cylinder[0].start))
return;
if (MATCH("cylinderendpressure", pressure, &dive->cylinder[0].end))
return;
- if (MATCH("gps", gps_location, dive))
+ if (MATCH("gps", gps_in_dive, dive))
return;
- if (MATCH("Place", gps_location, dive))
+ if (MATCH("Place", gps_in_dive, dive))
return;
if (MATCH("latitude", gps_lat, dive))
return;
@@ -1219,9 +1322,9 @@ static void try_to_fill_dive(struct dive *dive, const char *name, char *buf)
return;
if (MATCH("lon", gps_long, dive))
return;
- if (MATCH("location", utf8_string, &dive->location))
+ if (MATCH("location", add_dive_site, dive))
return;
- if (MATCH("name.dive", utf8_string, &dive->location))
+ if (MATCH("name.dive", add_dive_site, dive))
return;
if (MATCH("suit", utf8_string, &dive->suit))
return;
@@ -1290,6 +1393,27 @@ static void try_to_fill_trip(dive_trip_t **dive_trip_p, const char *name, char *
nonmatch("trip", name, buf);
}
+/* We're processing a divesite entry - try to fill the components */
+static void try_to_fill_dive_site(struct dive_site **ds_p, const char *name, char *buf)
+{
+ start_match("divesite", name, buf);
+
+ struct dive_site *ds = *ds_p;
+
+ if (MATCH("uuid", hex_value, &ds->uuid))
+ return;
+ if (MATCH("name", utf8_string, &ds->name))
+ return;
+ if (MATCH("description", utf8_string, &ds->description))
+ return;
+ if (MATCH("notes", utf8_string, &ds->notes))
+ return;
+ if (MATCH("gps", gps_location, ds))
+ return;
+
+ nonmatch("divesite", name, buf);
+}
+
/*
* While in some formats file boundaries are dive boundaries, in many
* others (as for example in our native format) there are
@@ -1305,7 +1429,7 @@ static void try_to_fill_trip(dive_trip_t **dive_trip_p, const char *name, char *
static bool is_dive(void)
{
return (cur_dive &&
- (cur_dive->location || cur_dive->when || cur_dive->dc.samples));
+ (cur_dive->dive_site_uuid || cur_dive->when || cur_dive->dc.samples));
}
static void reset_dc_info(struct divecomputer *dc)
@@ -1349,6 +1473,32 @@ static void dc_settings_end(void)
reset_dc_settings();
}
+static void dive_site_start(void)
+{
+ if (cur_dive_site)
+ return;
+ cur_dive_site = calloc(1, sizeof(struct dive_site));
+}
+
+static void dive_site_end(void)
+{
+ if (!cur_dive_site)
+ return;
+ if (cur_dive_site->uuid) {
+ uint32_t tmp = create_dive_site_with_gps(cur_dive_site->name, cur_dive_site->latitude, cur_dive_site->longitude);
+ struct dive_site *ds = get_dive_site_by_uuid(tmp);
+ ds->uuid = cur_dive_site->uuid;
+ ds->notes = cur_dive_site->notes;
+ ds->description = cur_dive_site->description;
+ if (verbose > 3)
+ printf("completed dive site uuid %x8 name {%s}\n", ds->uuid, ds->name);
+ }
+ free(cur_dive_site);
+ cur_dive_site = NULL;
+}
+
+// now we need to add the code to parse the parts of the divesite enry
+
static void dive_start(void)
{
if (cur_dive)
@@ -1527,37 +1677,54 @@ static void userid_stop(void)
in_userid = false;
}
-static void entry(const char *name, char *buf)
+static bool entry(const char *name, char *buf)
{
+ if (!strncmp(name, "version.program", sizeof("version.program") - 1) ||
+ !strncmp(name, "version.divelog", sizeof("version.divelog") - 1)) {
+ last_xml_version = atoi(buf);
+ if (last_xml_version < 3 && !v2_question_shown && !imported_via_xslt) {
+ // let's ask the user what they want to do about reverse geo coding
+ // and warn them that opening older XML files can take a while
+ // since C code shouldn't call the UI we set a global flag and bail
+ // from reading the file for now
+ abort_read_of_old_file = true;
+ return false;
+ }
+ }
if (in_userid) {
try_to_fill_userid(name, buf);
- return;
+ return true;
}
if (in_settings) {
try_to_fill_dc_settings(name, buf);
try_to_match_autogroup(name, buf);
- return;
+ return true;
+ }
+ if (cur_dive_site) {
+ try_to_fill_dive_site(&cur_dive_site, name, buf);
+ return true;
}
if (!cur_event.deleted) {
try_to_fill_event(name, buf);
- return;
+ return true;
}
if (cur_sample) {
try_to_fill_sample(cur_sample, name, buf);
- return;
+ return true;
}
if (cur_dc) {
try_to_fill_dc(cur_dc, name, buf);
- return;
+ return true;
}
if (cur_dive) {
try_to_fill_dive(cur_dive, name, buf);
- return;
+ return true;
}
if (cur_trip) {
try_to_fill_trip(&cur_trip, name, buf);
- return;
+ return true;
}
+ return true;
}
static const char *nodename(xmlNode *node, char *buf, int len)
@@ -1599,7 +1766,7 @@ static const char *nodename(xmlNode *node, char *buf, int len)
#define MAXNAME 32
-static void visit_one_node(xmlNode *node)
+static bool visit_one_node(xmlNode *node)
{
char *content;
static char buffer[MAXNAME];
@@ -1607,28 +1774,29 @@ static void visit_one_node(xmlNode *node)
content = node->content;
if (!content || xmlIsBlankNode(node))
- return;
+ return true;
name = nodename(node, buffer, sizeof(buffer));
- entry(name, content);
+ return entry(name, content);
}
-static void traverse(xmlNode *root);
+static bool traverse(xmlNode *root);
-static void traverse_properties(xmlNode *node)
+static bool traverse_properties(xmlNode *node)
{
xmlAttr *p;
+ bool ret = true;
for (p = node->properties; p; p = p->next)
- traverse(p->children);
+ if ((ret = traverse(p->children)) == false)
+ break;
+ return ret;
}
-static void visit(xmlNode *n)
+static bool visit(xmlNode *n)
{
- visit_one_node(n);
- traverse_properties(n);
- traverse(n->children);
+ return visit_one_node(n) && traverse_properties(n) && traverse(n->children);
}
static void DivingLog_importer(void)
@@ -1666,6 +1834,7 @@ static struct nesting {
} nesting[] = {
{ "divecomputerid", dc_settings_start, dc_settings_end },
{ "settings", settings_start, settings_end },
+ { "site", dive_site_start, dive_site_end },
{ "dive", dive_start, dive_end },
{ "Dive", dive_start, dive_end },
{ "trip", trip_start, trip_end },
@@ -1690,15 +1859,17 @@ static struct nesting {
{ NULL, }
};
-static void traverse(xmlNode *root)
+static bool traverse(xmlNode *root)
{
xmlNode *n;
+ bool ret = true;
for (n = root; n; n = n->next) {
struct nesting *rule = nesting;
if (!n->name) {
- visit(n);
+ if ((ret = visit(n)) == false)
+ break;
continue;
}
@@ -1710,10 +1881,12 @@ static void traverse(xmlNode *root)
if (rule->start)
rule->start();
- visit(n);
+ if ((ret = visit(n)) == false)
+ break;
if (rule->end)
rule->end();
}
+ return ret;
}
/* Per-file reset */
@@ -1760,6 +1933,7 @@ int parse_xml_buffer(const char *url, const char *buffer, int size,
{
xmlDoc *doc;
const char *res = preprocess_divelog_de(buffer);
+ int ret = 0;
target_table = table;
doc = xmlReadMemory(res, strlen(res), url, NULL, 0);
@@ -1774,11 +1948,14 @@ int parse_xml_buffer(const char *url, const char *buffer, int size,
reset_all();
dive_start();
doc = test_xslt_transforms(doc, params);
- traverse(xmlDocGetRootElement(doc));
+ if (!traverse(xmlDocGetRootElement(doc))) {
+ // we decided to give up on parsing... why?
+ ret = -1;
+ }
dive_end();
xmlFreeDoc(doc);
-
- return 0;
+ imported_via_xslt = false;
+ return ret;
}
void parse_mkvi_buffer(struct membuffer *txt, struct membuffer *csv, const char *starttime)
@@ -1861,13 +2038,24 @@ extern int dm4_events(void *handle, int columns, char **data, char **column)
strcpy(cur_event.name, "deco");
break;
case 22:
+ case 32:
/* 22 Mandatory safety stop violation */
+ /* 32 Deep stop violation */
strcpy(cur_event.name, "violation");
break;
+ case 30:
+ /* Tissue level warning */
+ strcpy(cur_event.name, "tissue warning");
+ break;
+ case 37:
+ /* Tank pressure alarm */
+ strcpy(cur_event.name, "tank pressure");
+ break;
case 257:
/* 257 Dive active */
- /* This seems to be given after surface
- * when descending again. Ignoring it. */
+ /* This seems to be given after surface when
+ * descending again. */
+ strcpy(cur_event.name, "surface");
break;
case 258:
/* 258 Bookmark */
@@ -1878,6 +2066,23 @@ extern int dm4_events(void *handle, int columns, char **data, char **column)
strcpy(cur_event.name, "bookmark");
}
break;
+ case 259:
+ /* Deep stop */
+ strcpy(cur_event.name, "Deep stop");
+ break;
+ case 260:
+ /* Deep stop */
+ strcpy(cur_event.name, "Deep stop cleared");
+ break;
+ case 266:
+ /* Mandatory safety stop activated */
+ strcpy(cur_event.name, "safety stop (mandatory)");
+ break;
+ case 267:
+ /* Mandatory safety stop deactivated */
+ /* DM5 shows this only on event list, not on the
+ * profile so skipping as well for now */
+ break;
default:
strcpy(cur_event.name, "unknown");
cur_event.value = atoi(data[2]);
@@ -1889,6 +2094,44 @@ extern int dm4_events(void *handle, int columns, char **data, char **column)
return 0;
}
+extern int dm5_cylinders(void *handle, int columns, char **data, char **column)
+{
+ cylinder_start();
+ if (data[7] && atoi(data[7]) > 0 && atoi(data[7]) < 350000)
+ cur_dive->cylinder[cur_cylinder_index].start.mbar = atoi(data[7]);
+ if (data[8] && atoi(data[8]) > 0 && atoi(data[8]) < 350000)
+ cur_dive->cylinder[cur_cylinder_index].end.mbar = (atoi(data[8]));
+ if (data[6]) {
+ /* DM5 shows tank size of 12 liters when the actual
+ * value is 0 (and using metric units). So we just use
+ * the same 12 liters when size is not available */
+ if (atof(data[6]) == 0.0 && cur_dive->cylinder[cur_cylinder_index].start.mbar)
+ cur_dive->cylinder[cur_cylinder_index].type.size.mliter = 12000;
+ else
+ cur_dive->cylinder[cur_cylinder_index].type.size.mliter = (atof(data[6])) * 1000;
+ }
+ if (data[2])
+ cur_dive->cylinder[cur_cylinder_index].gasmix.o2.permille = atoi(data[2]) * 10;
+ if (data[3])
+ cur_dive->cylinder[cur_cylinder_index].gasmix.he.permille = atoi(data[3]) * 10;
+ cylinder_end();
+ return 0;
+}
+
+extern int dm5_gaschange(void *handle, int columns, char **data, char **column)
+{
+ event_start();
+ if (data[0])
+ cur_event.time.seconds = atoi(data[0]);
+ if (data[1]) {
+ strcpy(cur_event.name, "gaschange");
+ cur_event.value = atof(data[1]);
+ }
+ event_end();
+
+ return 0;
+}
+
extern int dm4_tags(void *handle, int columns, char **data, char **column)
{
if (data[0])
@@ -2031,7 +2274,9 @@ extern int dm5_dive(void *param, int columns, char **data, char **column)
char *err = NULL;
char get_events_template[] = "select * from Mark where DiveId = %d";
char get_tags_template[] = "select Text from DiveTag where DiveId = %d";
- char get_events[64];
+ char get_cylinders_template[] = "select * from DiveMixture where DiveId = %d";
+ char get_gaschange_template[] = "select GasChangeTime,Oxygen,Helium from DiveGasChange join DiveMixture on DiveGasChange.DiveMixtureId=DiveMixture.DiveMixtureId where DiveId = %d";
+ char get_events[512];
dive_start();
cur_dive->number = atoi(data[0]);
@@ -2050,12 +2295,13 @@ extern int dm5_dive(void *param, int columns, char **data, char **column)
*/
settings_start();
dc_settings_start();
- if (data[4])
+ if (data[4]) {
utf8_string(data[4], &cur_settings.dc.serial_nr);
+ cur_settings.dc.deviceid = atoi(data[4]);
+ }
if (data[5])
utf8_string(data[5], &cur_settings.dc.model);
- cur_settings.dc.deviceid = 0xffffffff;
dc_settings_end();
settings_end();
@@ -2066,30 +2312,21 @@ extern int dm5_dive(void *param, int columns, char **data, char **column)
if (data[9])
cur_dive->dc.watertemp.mkelvin = C_to_mkelvin(atoi(data[9]));
- /*
- * TODO: handle multiple cylinders
- */
- cylinder_start();
- if (data[22] && atoi(data[22]) > 0)
- cur_dive->cylinder[cur_cylinder_index].start.mbar = atoi(data[22]);
- else if (data[10] && atoi(data[10]) > 0)
- cur_dive->cylinder[cur_cylinder_index].start.mbar = atoi(data[10]);
- if (data[23] && atoi(data[23]) > 0)
- cur_dive->cylinder[cur_cylinder_index].end.mbar = (atoi(data[23]));
- if (data[11] && atoi(data[11]) > 0)
- cur_dive->cylinder[cur_cylinder_index].end.mbar = (atoi(data[11]));
- if (data[12])
- cur_dive->cylinder[cur_cylinder_index].type.size.mliter = (atof(data[12])) * 1000;
- if (data[13])
- cur_dive->cylinder[cur_cylinder_index].type.workingpressure.mbar = (atoi(data[13]));
- if (data[20])
- cur_dive->cylinder[cur_cylinder_index].gasmix.o2.permille = atoi(data[20]) * 10;
- if (data[21])
- cur_dive->cylinder[cur_cylinder_index].gasmix.he.permille = atoi(data[21]) * 10;
- cylinder_end();
+ if (data[4]) {
+ cur_dive->dc.deviceid = atoi(data[4]);
+ }
+ if (data[5])
+ utf8_string(data[5], &cur_dive->dc.model);
+
+ snprintf(get_events, sizeof(get_events) - 1, get_cylinders_template, cur_dive->number);
+ retval = sqlite3_exec(handle, get_events, &dm5_cylinders, 0, &err);
+ if (retval != SQLITE_OK) {
+ fprintf(stderr, "%s", translate("gettextFromC", "Database query dm5_cylinders failed.\n"));
+ return 1;
+ }
if (data[14])
- cur_dive->dc.surface_pressure.mbar = (atoi(data[14]) * 1000);
+ cur_dive->dc.surface_pressure.mbar = (atoi(data[14]) / 100);
interval = data[16] ? atoi(data[16]) : 0;
sampleBlob = (unsigned const char *)data[24];
@@ -2141,6 +2378,13 @@ extern int dm5_dive(void *param, int columns, char **data, char **column)
}
}
+ snprintf(get_events, sizeof(get_events) - 1, get_gaschange_template, cur_dive->number);
+ retval = sqlite3_exec(handle, get_events, &dm5_gaschange, 0, &err);
+ if (retval != SQLITE_OK) {
+ fprintf(stderr, "%s", translate("gettextFromC", "Database query dm5_gaschange failed.\n"));
+ return 1;
+ }
+
snprintf(get_events, sizeof(get_events) - 1, get_events_template, cur_dive->number);
retval = sqlite3_exec(handle, get_events, &dm4_events, 0, &err);
if (retval != SQLITE_OK) {
@@ -2191,7 +2435,7 @@ int parse_dm5_buffer(sqlite3 *handle, const char *url, const char *buffer, int s
/* StartTime is converted from Suunto's nano seconds to standard
* time. We also need epoch, not seconds since year 1. */
- char get_dives[] = "select D.DiveId,StartTime/10000000-62135596800,Note,Duration,SourceSerialNumber,Source,MaxDepth,SampleInterval,StartTemperature,BottomTemperature,D.StartPressure,D.EndPressure,Size,CylinderWorkPressure,SurfacePressure,DiveTime,SampleInterval,ProfileBlob,TemperatureBlob,PressureBlob,Oxygen,Helium,MIX.StartPressure,MIX.EndPressure,SampleBlob FROM Dive AS D JOIN DiveMixture AS MIX ON D.DiveId=MIX.DiveId";
+ char get_dives[] = "select DiveId,StartTime/10000000-62135596800,Note,Duration,coalesce(SourceSerialNumber,SerialNumber),Source,MaxDepth,SampleInterval,StartTemperature,BottomTemperature,StartPressure,EndPressure,'','',SurfacePressure,DiveTime,SampleInterval,ProfileBlob,TemperatureBlob,PressureBlob,'','','','',SampleBlob FROM Dive where Deleted is null";
retval = sqlite3_exec(handle, get_dives, &dm5_dive, handle, &err);
@@ -2291,7 +2535,7 @@ extern int shearwater_dive(void *param, int columns, char **data, char **column)
cur_dive->when = (time_t)(atol(data[1]));
if (data[2])
- utf8_string(data[2], &cur_dive->location);
+ add_dive_site(data[2], cur_dive);
if (data[3])
utf8_string(data[3], &cur_dive->buddy);
if (data[4])
@@ -2388,19 +2632,21 @@ extern int cobalt_visibility(void *handle, int columns, char **data, char **colu
extern int cobalt_location(void *handle, int columns, char **data, char **column)
{
+ static char *location = NULL;
if (data[0]) {
- if (cur_dive->location) {
- char *tmp = malloc(strlen(cur_dive->location) + strlen(data[0]) + 4);
+ if (location) {
+ char *tmp = malloc(strlen(location) + strlen(data[0]) + 4);
if (!tmp)
return -1;
- sprintf(tmp, "%s / %s", cur_dive->location, data[0]);
- free(cur_dive->location);
- cur_dive->location = tmp;
+ sprintf(tmp, "%s / %s", location, data[0]);
+ free(location);
+ location = NULL;
+ cur_dive->dive_site_uuid = create_dive_site(tmp);
+ free(tmp);
} else {
- utf8_string(data[0], &cur_dive->location);
+ location = strdup(data[0]);
}
}
-
return 0;
}
@@ -2448,13 +2694,20 @@ extern int cobalt_dive(void *param, int columns, char **data, char **column)
*/
settings_start();
dc_settings_start();
- if (data[9])
+ if (data[9]) {
utf8_string(data[9], &cur_settings.dc.serial_nr);
+ cur_settings.dc.deviceid = atoi(data[9]);
+ cur_settings.dc.model = strdup("Cobalt import");
+ }
- cur_settings.dc.deviceid = 0xffffffff;
dc_settings_end();
settings_end();
+ if (data[9]) {
+ cur_dive->dc.deviceid = atoi(data[9]);
+ cur_dive->dc.model = strdup("Cobalt import");
+ }
+
snprintf(get_buffer, sizeof(get_buffer) - 1, get_cylinder_template, cur_dive->number);
retval = sqlite3_exec(handle, get_buffer, &cobalt_cylinders, 0, &err);
if (retval != SQLITE_OK) {
@@ -2529,7 +2782,7 @@ int parse_cobalt_buffer(sqlite3 *handle, const char *url, const char *buffer, in
char *err = NULL;
target_table = table;
- char get_dives[] = "select Id,strftime('%s',DiveStartTime),LocationId,'buddy','notes',Units,(MaxDepthPressure*10000/SurfacePressure)-10000,DiveMinutes,SurfacePressure,SerialNumber,'model' from Dive";
+ char get_dives[] = "select Id,strftime('%s',DiveStartTime),LocationId,'buddy','notes',Units,(MaxDepthPressure*10000/SurfacePressure)-10000,DiveMinutes,SurfacePressure,SerialNumber,'model' from Dive where IsViewDeleted = 0";
retval = sqlite3_exec(handle, get_dives, &cobalt_dive, handle, &err);
@@ -2563,8 +2816,8 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size)
// (ptr[7] << 8) + ptr[6] Is "Serial"
snprintf(serial, sizeof(serial), "%d", (ptr[7] << 8) + ptr[6]);
cur_dc->serial = strdup(serial);
- // Dive start time in seconds since 2000-01-01 12:00 UTC +0
- cur_dc->when = (ptr[11] << 24) + (ptr[10] << 16) + (ptr[9] << 8) + ptr[8] + 946728000;
+ // Dive start time in seconds since 2000-01-01 00:00
+ cur_dc->when = (ptr[11] << 24) + (ptr[10] << 16) + (ptr[9] << 8) + ptr[8] + 946684800;
cur_dive->when = cur_dc->when;
cur_dc->duration.seconds = ((ptr[14] & 0xFE) << 16) + (ptr[13] << 8) + ptr[12];
@@ -2903,7 +3156,7 @@ static xmlDoc *test_xslt_transforms(xmlDoc *doc, const char **params)
}
free((void *)attribute);
}
-
+ imported_via_xslt = true;
xmlSubstituteEntitiesDefault(1);
xslt = get_stylesheet(info->file);
if (xslt == NULL) {