int save_dives_logic(const char *filename, const bool select_only) { struct membuffer buf = { 0 }; FILE *f; void *git; const char *branch; int error; git = is_git_repository(filename, &branch); if (git) return git_save_dives(git, branch, select_only); try_to_backup(filename); save_dives_buffer(&buf, select_only); error = -1; f = subsurface_fopen(filename, "w"); if (f) { flush_buffer(&buf, f); error = fclose(f); } if (error) report_error("Save failed (%s)", strerror(errno)); free_buffer(&buf); return error; }
int export_dives_xslt(const char *filename, const bool selected, const int units, const char *export_xslt) { FILE *f; struct membuffer buf = { 0 }; xmlDoc *doc; xsltStylesheetPtr xslt = NULL; xmlDoc *transformed; int res = 0; char *params[3]; int pnr = 0; char unitstr[3]; if (verbose) fprintf(stderr, "export_dives_xslt with stylesheet %s\n", export_xslt); if (!filename) return report_error("No filename for export"); /* Save XML to file and convert it into a memory buffer */ save_dives_buffer(&buf, selected); /* * Parse the memory buffer into XML document and * transform it to selected export format, finally dumping * the XML into a character buffer. */ doc = xmlReadMemory(buf.buffer, buf.len, "divelog", NULL, 0); free_buffer(&buf); if (!doc) return report_error("Failed to read XML memory"); /* Convert to export format */ xslt = get_stylesheet(export_xslt); if (!xslt) return report_error("Failed to open export conversion stylesheet"); snprintf(unitstr, 3, "%d", units); params[pnr++] = "units"; params[pnr++] = unitstr; params[pnr++] = NULL; transformed = xsltApplyStylesheet(xslt, doc, (const char **)params); xmlFreeDoc(doc); /* Write the transformed export to file */ f = subsurface_fopen(filename, "w"); if (f) { xsltSaveResultToFile(f, transformed, xslt); fclose(f); /* Check write errors? */ } else { res = report_error("Failed to open %s for writing (%s)", filename, strerror(errno)); } xsltFreeStylesheet(xslt); xmlFreeDoc(transformed); return res; }
int export_dives_xslt(const char *filename, const bool selected, const char *export_xslt) { FILE *f; struct membuffer buf = { 0 }; xmlDoc *doc; xsltStylesheetPtr xslt = NULL; xmlDoc *transformed; if (!filename) return report_error("No filename for export"); /* Save XML to file and convert it into a memory buffer */ save_dives_buffer(&buf, selected); /* * Parse the memory buffer into XML document and * transform it to selected export format, finally dumping * the XML into a character buffer. */ doc = xmlReadMemory(buf.buffer, buf.len, "divelog", NULL, 0); free_buffer(&buf); if (!doc) return report_error("Failed to read XML memory"); /* Convert to export format */ xslt = get_stylesheet(export_xslt); if (!xslt) return report_error("Failed to open export conversion stylesheet"); transformed = xsltApplyStylesheet(xslt, doc, NULL); xsltFreeStylesheet(xslt); xmlFreeDoc(doc); /* Write the transformed export to file */ f = subsurface_fopen(filename, "w"); if (!f) return report_error("Failed to open %s for writing (%s)", filename, strerror(errno)); xmlDocFormatDump(f, transformed, 1); xmlFreeDoc(transformed); fclose(f); /* Check write errors? */ return 0; }
QString ConfigureDiveComputer::dc_open(device_data_t *data) { FILE *fp = NULL; dc_status_t rc; if (data->libdc_log) fp = subsurface_fopen(logfile_name, "w"); data->libdc_logfile = fp; rc = dc_context_new(&data->context); if (rc != DC_STATUS_SUCCESS) { return tr("Unable to create libdivecomputer context"); } if (fp) { dc_context_set_loglevel(data->context, DC_LOGLEVEL_ALL); dc_context_set_logfunc(data->context, logfunc, fp); fprintf(data->libdc_logfile, "Subsurface: v%s, ", subsurface_git_version()); fprintf(data->libdc_logfile, "built with libdivecomputer v%s\n", dc_version(NULL)); } rc = divecomputer_device_open(data); if (rc != DC_STATUS_SUCCESS) { report_error(errmsg(rc)); } else { rc = dc_device_open(&data->device, data->context, data->descriptor, data->iostream); } if (rc != DC_STATUS_SUCCESS) { return tr("Could not a establish connection to the dive computer."); } setState(OPEN); return NULL; }
void DiveLogExportDialog::export_depths(const char *filename, const bool selected_only) { FILE *f; struct dive *dive; depth_t depth; int i; const char *unit = NULL; struct membuffer buf = {}; for_each_dive (i, dive) { if (selected_only && !dive->selected) continue; FOR_EACH_PICTURE (dive) { int n = dive->dc.samples; struct sample *s = dive->dc.sample; depth.mm = 0; while (--n >= 0 && (int32_t)s->time.seconds <= picture->offset.seconds) { depth.mm = s->depth.mm; s++; } put_format(&buf, "%s\t%.1f", picture->filename, get_depth_units(depth.mm, NULL, &unit)); put_format(&buf, "%s\n", unit); } } f = subsurface_fopen(filename, "w+"); if (!f) { report_error(tr("Can't open file %s").toUtf8().data(), filename); } else { flush_buffer(&buf, f); /*check for writing errors? */ fclose(f); } free_buffer(&buf); }
/* * OSTCTools stores the raw dive data in heavily padded files, one dive * each file. So it's not necessary to iterate once and again on a parsing * function. Actually there's only one kind of archive for every DC model. */ void ostctools_import(const char *file, struct dive_table *divetable) { FILE *archive; device_data_t *devdata = calloc(1, sizeof(device_data_t)); dc_family_t dc_fam; unsigned char *buffer = calloc(65536, 1), *uc_tmp; char *tmp; struct dive *ostcdive = alloc_dive(); dc_status_t rc = 0; int model, ret, i = 0; unsigned int serial; struct extra_data *ptr; // Open the archive if ((archive = subsurface_fopen(file, "rb")) == NULL) { report_error(translate("gettextFromC", "Failed to read '%s'"), file); free(ostcdive); goto out; } // Read dive number from the log uc_tmp = calloc(2, 1); fseek(archive, 258, 0); fread(uc_tmp, 1, 2, archive); ostcdive->number = uc_tmp[0] + (uc_tmp[1] << 8); free(uc_tmp); // Read device's serial number uc_tmp = calloc(2, 1); fseek(archive, 265, 0); fread(uc_tmp, 1, 2, archive); serial = uc_tmp[0] + (uc_tmp[1] << 8); free(uc_tmp); // Read dive's raw data, header + profile fseek(archive, 456, 0); while (!feof(archive)) { fread(buffer + i, 1, 1, archive); if (buffer[i] == 0xFD && buffer[i - 1] == 0xFD) break; i++; } // Try to determine the dc family based on the header type if (buffer[2] == 0x20 || buffer[2] == 0x21) { dc_fam = DC_FAMILY_HW_OSTC; } else { switch (buffer[8]) { case 0x22: dc_fam = DC_FAMILY_HW_FROG; break; case 0x23: dc_fam = DC_FAMILY_HW_OSTC3; break; default: report_error(translate("gettextFromC", "Unknown DC in dive %d"), ostcdive->number); free(ostcdive); fclose(archive); goto out; } } // Try to determine the model based on serial number switch (dc_fam) { case DC_FAMILY_HW_OSTC: if (serial > 7000) model = 3; //2C else if (serial > 2048) model = 2; //2N else if (serial > 300) model = 1; //MK2 else model = 0; //OSTC break; case DC_FAMILY_HW_FROG: model = 0; break; default: if (serial > 10000) model = 0x12; //Sport else model = 0x0A; //OSTC3 } // Prepare data to pass to libdivecomputer. ret = ostc_prepare_data(model, dc_fam, devdata); if (ret == 0) { report_error(translate("gettextFromC", "Unknown DC in dive %d"), ostcdive->number); free(ostcdive); fclose(archive); goto out; } tmp = calloc(strlen(devdata->vendor) + strlen(devdata->model) + 28, 1); sprintf(tmp, "%s %s (Imported from OSTCTools)", devdata->vendor, devdata->model); ostcdive->dc.model = copy_string(tmp); free(tmp); // Parse the dive data rc = libdc_buffer_parser(ostcdive, devdata, buffer, i + 1); if (rc != DC_STATUS_SUCCESS) report_error(translate("gettextFromC", "Error - %s - parsing dive %d"), errmsg(rc), ostcdive->number); // Serial number is not part of the header nor the profile, so libdc won't // catch it. If Serial is part of the extra_data, and set to zero, remove // it from the list and add again. tmp = calloc(12, 1); sprintf(tmp, "%d", serial); ostcdive->dc.serial = copy_string(tmp); free(tmp); if (ostcdive->dc.extra_data) { ptr = ostcdive->dc.extra_data; while (strcmp(ptr->key, "Serial")) ptr = ptr->next; if (!strcmp(ptr->value, "0")) { add_extra_data(&ostcdive->dc, "Serial", ostcdive->dc.serial); *ptr = *(ptr)->next; } } else { add_extra_data(&ostcdive->dc, "Serial", ostcdive->dc.serial); } record_dive_to_table(ostcdive, divetable); mark_divelist_changed(true); sort_table(divetable); fclose(archive); out: free(devdata); free(buffer); }
// TODO: This looks like should be ported to C code. or a big part of it. bool DivelogsDeWebServices::prepare_dives_for_divelogs(const QString &tempfile, const bool selected) { static const char errPrefix[] = "divelog.de-upload:"; if (!amount_selected) { report_error(tr("no dives were selected").toUtf8()); return false; } xsltStylesheetPtr xslt = NULL; struct zip *zip; xslt = get_stylesheet("divelogs-export.xslt"); if (!xslt) { qDebug() << errPrefix << "missing stylesheet"; return false; } int error_code; zip = zip_open(QFile::encodeName(QDir::toNativeSeparators(tempfile)), ZIP_CREATE, &error_code); if (!zip) { char buffer[1024]; zip_error_to_str(buffer, sizeof buffer, error_code, errno); report_error(tr("failed to create zip file for upload: %s").toUtf8(), buffer); return false; } /* walk the dive list in chronological order */ int i; struct dive *dive; for_each_dive (i, dive) { FILE *f; char filename[PATH_MAX]; int streamsize; char *membuf; xmlDoc *transformed; struct zip_source *s; /* * Get the i'th dive in XML format so we can process it. * We need to save to a file before we can reload it back into memory... */ if (selected && !dive->selected) continue; QString innerTmpFile = tempfile; QString tmpSuffix = QString::number(qrand() % 9999) + ".tmp"; innerTmpFile.replace(".dld", tmpSuffix); f = subsurface_fopen(QFile::encodeName(QDir::toNativeSeparators(innerTmpFile)), "w+"); if (!f) { report_error(tr("cannot create temporary file: %s").toUtf8(), qt_error_string().toUtf8().data()); goto error_close_zip; } save_dive(f, dive); fseek(f, 0, SEEK_END); streamsize = ftell(f); rewind(f); membuf = (char *)malloc(streamsize + 1); if (!membuf || (streamsize = fread(membuf, 1, streamsize, f)) == 0) { report_error(tr("internal error: %s").toUtf8(), qt_error_string().toUtf8().data()); fclose(f); free((void *)membuf); goto error_close_zip; } membuf[streamsize] = 0; fclose(f); unlink(QFile::encodeName(QDir::toNativeSeparators(innerTmpFile))); /* * Parse the memory buffer into XML document and * transform it to divelogs.de format, finally dumping * the XML into a character buffer. */ xmlDoc *doc = xmlReadMemory(membuf, streamsize, "divelog", NULL, 0); if (!doc) { qWarning() << errPrefix << "could not parse back into memory the XML file we've just created!"; report_error(tr("internal error").toUtf8()); free((void *)membuf); goto error_close_zip; } free((void *)membuf); transformed = xsltApplyStylesheet(xslt, doc, NULL); xmlDocDumpMemory(transformed, (xmlChar **)&membuf, &streamsize); xmlFreeDoc(doc); xmlFreeDoc(transformed); /* * Save the XML document into a zip file. */ snprintf(filename, PATH_MAX, "%d.xml", i + 1); s = zip_source_buffer(zip, membuf, streamsize, 1); if (s) { int64_t ret = zip_add(zip, filename, s); if (ret == -1) qDebug() << errPrefix << "failed to include dive:" << i; } }
/* * OSTCTools stores the raw dive data in heavily padded files, one dive * each file. So it's not necesary to iterate once and again on a parsing * function. Actually there's only one kind of archive for every DC model. */ void ostctools_import(const char *file, struct dive_table *divetable) { FILE *archive; device_data_t *devdata = calloc(1, sizeof(device_data_t)); dc_family_t dc_fam; unsigned char *buffer = calloc(65536, 1), *tmp; struct dive *ostcdive = alloc_dive(); dc_status_t rc = 0; int model = 0, i = 0; unsigned int serial; struct extra_data *ptr; // Open the archive if ((archive = subsurface_fopen(file, "rb")) == NULL) { report_error(translate("gettextFromC", "Error: couldn't open the file")); return; } // Read dive number from the log tmp = calloc(2,1); fseek(archive, 258, 0); fread(tmp, 1, 2, archive); ostcdive->number = tmp[0] + (tmp[1] << 8); free(tmp); // Read device's serial number tmp = calloc(2, 1); fseek(archive, 265, 0); fread(tmp, 1, 2, archive); serial = tmp[0] + (tmp[1] << 8); free(tmp); // Read dive's raw data, header + profile fseek(archive, 456, 0); while (!feof(archive)) { fread(buffer+i, 1, 1, archive); if (buffer[i] == 0xFD && buffer[i-1] == 0xFD) break; i++; } // Try to determine the dc family based on the header type switch (buffer[2]) { case 0x20: case 0x21: dc_fam = DC_FAMILY_HW_OSTC; break; case 0x22: dc_fam = DC_FAMILY_HW_FROG; break; case 0x23: dc_fam = DC_FAMILY_HW_OSTC3; break; } // Prepare data to pass to libdivecomputer. OSTC protocol doesn't include // a model number so will use 0. ostc_prepare_data(model, dc_fam, devdata); tmp = calloc(strlen(devdata->vendor)+strlen(devdata->model)+28,1); sprintf(tmp,"%s %s (Imported from OSTCTools)", devdata->vendor, devdata->model); ostcdive->dc.model = copy_string(tmp); free(tmp); // Parse the dive data rc = libdc_buffer_parser(ostcdive, devdata, buffer, i+1); if (rc != DC_STATUS_SUCCESS) report_error("Libdc returned error -%s- for dive %d", errmsg(rc), ostcdive->number); // Serial number is not part of the header nor the profile, so libdc won't // catch it. If Serial is part of the extra_data, and set to zero, remove // it from the list and add again. tmp = calloc(12,1); sprintf(tmp, "%d", serial); ostcdive->dc.serial = copy_string(tmp); free(tmp); ptr = ostcdive->dc.extra_data; while (strcmp(ptr->key, "Serial")) ptr = ptr->next; if (!strcmp(ptr->value, "0")) { add_extra_data(&ostcdive->dc, "Serial", ostcdive->dc.serial); *ptr = *(ptr)->next; } free(devdata); free(buffer); record_dive_to_table(ostcdive, divetable); mark_divelist_changed(true); sort_table(divetable); fclose(archive); }
QString ConfigureDiveComputer::dc_open(device_data_t *data) { FILE *fp = NULL; dc_status_t rc; if (data->libdc_log) fp = subsurface_fopen(logfile_name, "w"); data->libdc_logfile = fp; rc = dc_context_new(&data->context); if (rc != DC_STATUS_SUCCESS) { return tr("Unable to create libdivecomputer context"); } if (fp) { dc_context_set_loglevel(data->context, DC_LOGLEVEL_ALL); dc_context_set_logfunc(data->context, logfunc, fp); } #if defined(SSRF_CUSTOM_SERIAL) if (data->bluetooth_mode) { #if defined(BT_SUPPORT) && defined(SSRF_CUSTOM_SERIAL) rc = dc_context_set_custom_serial(data->context, get_qt_serial_ops()); #endif #ifdef SERIAL_FTDI } else if (!strcmp(data->devname, "ftdi")) { rc = dc_context_set_custom_serial(data->context, &serial_ftdi_ops); #endif } if (rc != DC_STATUS_SUCCESS) { report_error(errmsg(rc)); } else { #else { #endif rc = dc_device_open(&data->device, data->context, data->descriptor, data->devname); } if (rc != DC_STATUS_SUCCESS) { return tr("Could not a establish connection to the dive computer."); } setState(OPEN); return NULL; } void ConfigureDiveComputer::dc_close(device_data_t *data) { if (data->device) dc_device_close(data->device); data->device = NULL; if (data->context) dc_context_free(data->context); data->context = NULL; if (data->libdc_logfile) fclose(data->libdc_logfile); setState(INITIAL); }