diff options
author | Robert C. Helling <helling@atdotde.de> | 2018-09-10 14:47:56 +0200 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2018-09-13 08:16:54 -0700 |
commit | afe363fa8569c0634e5bc20dc54c204533a638d7 (patch) | |
tree | 556d189afc6fb2a9c2c9573345ade233635dffe8 | |
parent | adbb1488e8ae3ff06983c11f954d6079cfc48cce (diff) | |
download | subsurface-afe363fa8569c0634e5bc20dc54c204533a638d7.tar.gz |
Optional anonymization upon export
Add a checkbox that triggers replacement of all English characters by
x's in notes, buddy, dive guide and (while we are at it) suit.
This is ment for people sharing logs for debugging that are concious
about privacy issues. It leaves the lenth of strings in tact as well
as special charcters as those might be needed to track down a particular
parsing problem.
Signed-off-by: Robert C. Helling <helling@atdotde.de>
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | core/dive.h | 8 | ||||
-rw-r--r-- | core/save-xml.c | 77 | ||||
-rw-r--r-- | desktop-widgets/divelogexportdialog.cpp | 4 | ||||
-rw-r--r-- | desktop-widgets/divelogexportdialog.ui | 44 | ||||
-rw-r--r-- | desktop-widgets/subsurfacewebservices.cpp | 2 | ||||
-rw-r--r-- | smtk-import/smrtk2ssrfc_window.cpp | 2 | ||||
-rw-r--r-- | smtk-import/smtk_standalone.cpp | 2 | ||||
-rw-r--r-- | tests/testparse.cpp | 16 | ||||
-rw-r--r-- | tests/testplan.cpp | 26 |
10 files changed, 114 insertions, 68 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index ef3dd3975..c44d80406 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ - Mobil: setting for developer menu entry is remembered across sessions - Mobile: remove UI components of the Webservice GPS interaction +- Deskop: Add anonymization option to divelog export - Desktop: remove UI components of the Webservice GPS import. This functionality will be fully replaced by "apply on device". - DLF import: record battery status at end of dive diff --git a/core/dive.h b/core/dive.h index dd3bbc6a8..277050f5e 100644 --- a/core/dive.h +++ b/core/dive.h @@ -511,12 +511,12 @@ extern int parse_seabear_log(const char *filename); extern int parse_txt_file(const char *filename, const char *csv); extern int parse_manual_file(const char *filename, char **params, int pnr); extern int save_dives(const char *filename); -extern int save_dives_logic(const char *filename, bool select_only); -extern int save_dive(FILE *f, struct dive *dive); -extern int export_dives_xslt(const char *filename, const bool selected, const int units, const char *export_xslt); +extern int save_dives_logic(const char *filename, bool select_only, bool anonymize); +extern int save_dive(FILE *f, struct dive *dive, bool anonymize); +extern int export_dives_xslt(const char *filename, const bool selected, const int units, const char *export_xslt, bool anonymize); struct membuffer; -extern void save_one_dive_to_mb(struct membuffer *b, struct dive *dive); +extern void save_one_dive_to_mb(struct membuffer *b, struct dive *dive, bool anonymize); int cylinderuse_from_text(const char *text); diff --git a/core/save-xml.c b/core/save-xml.c index 653c1f298..96932c900 100644 --- a/core/save-xml.c +++ b/core/save-xml.c @@ -63,6 +63,35 @@ static void show_utf8(struct membuffer *b, const char *text, const char *pre, co free(cleaned); } +static void blankout(char *c) +{ + while(*c) { + switch (*c) { + case 'A'...'Z': + *c = 'X'; + break; + case 'a'...'z': + *c = 'x'; + break; + default: + ; + } + ++c; + } +} + +static void show_utf8_blanked(struct membuffer *b, const char *text, const char *pre, const char *post, int is_attribute, bool anonymize) +{ + if (!text) + return; + char *copy = strdup(text); + + if (anonymize) + blankout(copy); + show_utf8(b, copy, pre, post, is_attribute); + free(copy); +} + static void save_depths(struct membuffer *b, struct divecomputer *dc) { /* What's the point of this dive entry again? */ @@ -119,12 +148,12 @@ static void save_salinity(struct membuffer *b, struct divecomputer *dc) put_string(b, " />\n"); } -static void save_overview(struct membuffer *b, struct dive *dive) +static void save_overview(struct membuffer *b, struct dive *dive, bool anonymize) { - show_utf8(b, dive->divemaster, " <divemaster>", "</divemaster>\n", 0); - show_utf8(b, dive->buddy, " <buddy>", "</buddy>\n", 0); - show_utf8(b, dive->notes, " <notes>", "</notes>\n", 0); - show_utf8(b, dive->suit, " <suit>", "</suit>\n", 0); + show_utf8_blanked(b, dive->divemaster, " <divemaster>", "</divemaster>\n", 0, anonymize); + show_utf8_blanked(b, dive->buddy, " <buddy>", "</buddy>\n", 0, anonymize); + show_utf8_blanked(b, dive->notes, " <notes>", "</notes>\n", 0, anonymize); + show_utf8_blanked(b, dive->suit, " <suit>", "</suit>\n", 0, anonymize); } static void put_gasmix(struct membuffer *b, struct gasmix mix) @@ -443,7 +472,7 @@ static void save_picture(struct membuffer *b, struct picture *pic) put_string(b, "/>\n"); } -void save_one_dive_to_mb(struct membuffer *b, struct dive *dive) +void save_one_dive_to_mb(struct membuffer *b, struct dive *dive, bool anonymize) { struct divecomputer *dc; @@ -469,7 +498,7 @@ void save_one_dive_to_mb(struct membuffer *b, struct dive *dive) FRACTION(dive->dc.duration.seconds, 60)); else put_format(b, ">\n"); - save_overview(b, dive); + save_overview(b, dive, anonymize); save_cylinder_info(b, dive); save_weightsystem_info(b, dive); save_dive_temperature(b, dive); @@ -481,17 +510,17 @@ void save_one_dive_to_mb(struct membuffer *b, struct dive *dive) put_format(b, "</dive>\n"); } -int save_dive(FILE *f, struct dive *dive) +int save_dive(FILE *f, struct dive *dive, bool anonymize) { struct membuffer buf = { 0 }; - save_one_dive_to_mb(&buf, dive); + save_one_dive_to_mb(&buf, dive, anonymize); flush_buffer(&buf, f); /* Error handling? */ return 0; } -static void save_trip(struct membuffer *b, dive_trip_t *trip) +static void save_trip(struct membuffer *b, dive_trip_t *trip, bool anonymize) { int i; struct dive *dive; @@ -510,7 +539,7 @@ static void save_trip(struct membuffer *b, dive_trip_t *trip) */ for_each_dive(i, dive) { if (dive->divetrip == trip) - save_one_dive_to_mb(b, dive); + save_one_dive_to_mb(b, dive, anonymize); } put_format(b, "</trip>\n"); @@ -550,10 +579,10 @@ static void save_one_device(void *_f, const char *model, uint32_t deviceid, int save_dives(const char *filename) { - return save_dives_logic(filename, false); + return save_dives_logic(filename, false, false); } -void save_dives_buffer(struct membuffer *b, const bool select_only) +void save_dives_buffer(struct membuffer *b, const bool select_only, bool anonymize) { int i; struct dive *dive; @@ -600,21 +629,21 @@ void save_dives_buffer(struct membuffer *b, const bool select_only) continue; put_format(b, "<site uuid='%8x'", ds->uuid); - show_utf8(b, ds->name, " name='", "'", 1); + show_utf8_blanked(b, ds->name, " name='", "'", 1, anonymize); if (ds->latitude.udeg || ds->longitude.udeg) { put_degrees(b, ds->latitude, " gps='", " "); put_degrees(b, ds->longitude, "", "'"); } - show_utf8(b, ds->description, " description='", "'", 1); + show_utf8_blanked(b, ds->description, " description='", "'", 1, anonymize); put_format(b, ">\n"); - show_utf8(b, ds->notes, " <notes>", " </notes>\n", 0); + show_utf8_blanked(b, ds->notes, " <notes>", " </notes>\n", 0, anonymize); if (ds->taxonomy.nr) { for (int j = 0; j < ds->taxonomy.nr; j++) { struct taxonomy *t = &ds->taxonomy.category[j]; if (t->category != TC_NONE && t->value) { put_format(b, " <geo cat='%d'", t->category); put_format(b, " origin='%d'", t->origin); - show_utf8(b, t->value, " value='", "'/>\n", 1); + show_utf8_blanked(b, t->value, " value='", "'/>\n", 1, anonymize); } } } @@ -630,14 +659,14 @@ void save_dives_buffer(struct membuffer *b, const bool select_only) if (!dive->selected) continue; - save_one_dive_to_mb(b, dive); + save_one_dive_to_mb(b, dive, anonymize); } else { trip = dive->divetrip; /* Bare dive without a trip? */ if (!trip) { - save_one_dive_to_mb(b, dive); + save_one_dive_to_mb(b, dive, anonymize); continue; } @@ -647,7 +676,7 @@ void save_dives_buffer(struct membuffer *b, const bool select_only) /* We haven't seen this trip before - save it and all dives */ trip->saved = 1; - save_trip(b, trip); + save_trip(b, trip, anonymize); } } put_format(b, "</dives>\n</divelog>\n"); @@ -710,7 +739,7 @@ static void try_to_backup(const char *filename) } } -int save_dives_logic(const char *filename, const bool select_only) +int save_dives_logic(const char *filename, const bool select_only, bool anonymize) { struct membuffer buf = { 0 }; FILE *f; @@ -722,7 +751,7 @@ int save_dives_logic(const char *filename, const bool select_only) if (git) return git_save_dives(git, branch, remote, select_only); - save_dives_buffer(&buf, select_only); + save_dives_buffer(&buf, select_only, anonymize); if (same_string(filename, "-")) { f = stdout; @@ -742,7 +771,7 @@ int save_dives_logic(const char *filename, const bool select_only) return error; } -int export_dives_xslt(const char *filename, const bool selected, const int units, const char *export_xslt) +int export_dives_xslt(const char *filename, const bool selected, const int units, const char *export_xslt, bool anonymize) { FILE *f; struct membuffer buf = { 0 }; @@ -761,7 +790,7 @@ int export_dives_xslt(const char *filename, const bool selected, const int units return report_error("No filename for export"); /* Save XML to file and convert it into a memory buffer */ - save_dives_buffer(&buf, selected); + save_dives_buffer(&buf, selected, anonymize); /* * Parse the memory buffer into XML document and diff --git a/desktop-widgets/divelogexportdialog.cpp b/desktop-widgets/divelogexportdialog.cpp index 9c21c4ff3..46e121d6c 100644 --- a/desktop-widgets/divelogexportdialog.cpp +++ b/desktop-widgets/divelogexportdialog.cpp @@ -157,7 +157,7 @@ void DiveLogExportDialog::on_buttonBox_accepted() if (!filename.contains('.')) filename.append(".ssrf"); QByteArray bt = QFile::encodeName(filename); - save_dives_logic(bt.data(), ui->exportSelected->isChecked()); + save_dives_logic(bt.data(), ui->exportSelected->isChecked(), ui->anonymize->isChecked()); } } else if (ui->exportImageDepths->isChecked()) { filename = QFileDialog::getSaveFileName(this, tr("Save image depths"), lastDir); @@ -183,7 +183,7 @@ void DiveLogExportDialog::on_buttonBox_accepted() qPrefDisplay::set_lastDir(fileInfo.dir().path()); // the non XSLT exports are called directly above, the XSLT based ons are called here if (!stylesheet.isEmpty()) { - future = QtConcurrent::run(export_dives_xslt, filename.toUtf8(), ui->exportSelected->isChecked(), ui->CSVUnits_2->currentIndex(), stylesheet.toUtf8()); + future = QtConcurrent::run(export_dives_xslt, filename.toUtf8(), ui->exportSelected->isChecked(), ui->CSVUnits_2->currentIndex(), stylesheet.toUtf8(), ui->anonymize->isChecked()); MainWindow::instance()->getNotificationWidget()->showNotification(tr("Please wait, exporting..."), KMessageWidget::Information); MainWindow::instance()->getNotificationWidget()->setFuture(future); } diff --git a/desktop-widgets/divelogexportdialog.ui b/desktop-widgets/divelogexportdialog.ui index 0d02d9fd8..f864902d2 100644 --- a/desktop-widgets/divelogexportdialog.ui +++ b/desktop-widgets/divelogexportdialog.ui @@ -279,12 +279,15 @@ <item> <widget class="QGroupBox" name="groupBox"> <property name="enabled"> - <bool>false</bool> + <bool>true</bool> </property> <property name="title"> - <string>CSV units</string> + <string>Options</string> </property> <widget class="QComboBox" name="CSVUnits_2"> + <property name="enabled"> + <bool>false</bool> + </property> <property name="geometry"> <rect> <x>30</x> @@ -304,6 +307,19 @@ </property> </item> </widget> + <widget class="QCheckBox" name="anonymize"> + <property name="geometry"> + <rect> + <x>10</x> + <y>50</y> + <width>111</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Anonymize</string> + </property> + </widget> </widget> </item> </layout> @@ -552,7 +568,7 @@ <hints> <hint type="sourcelabel"> <x>248</x> - <y>254</y> + <y>397</y> </hint> <hint type="destinationlabel"> <x>157</x> @@ -568,7 +584,7 @@ <hints> <hint type="sourcelabel"> <x>316</x> - <y>260</y> + <y>397</y> </hint> <hint type="destinationlabel"> <x>286</x> @@ -579,32 +595,32 @@ <connection> <sender>exportCSV</sender> <signal>toggled(bool)</signal> - <receiver>groupBox</receiver> + <receiver>CSVUnits_2</receiver> <slot>setEnabled(bool)</slot> <hints> <hint type="sourcelabel"> - <x>20</x> - <y>20</y> + <x>39</x> + <y>149</y> </hint> <hint type="destinationlabel"> - <x>20</x> - <y>20</y> + <x>322</x> + <y>171</y> </hint> </hints> </connection> <connection> <sender>exportCSVDetails</sender> <signal>toggled(bool)</signal> - <receiver>groupBox</receiver> + <receiver>CSVUnits_2</receiver> <slot>setEnabled(bool)</slot> <hints> <hint type="sourcelabel"> - <x>20</x> - <y>20</y> + <x>39</x> + <y>168</y> </hint> <hint type="destinationlabel"> - <x>20</x> - <y>20</y> + <x>322</x> + <y>171</y> </hint> </hints> </connection> diff --git a/desktop-widgets/subsurfacewebservices.cpp b/desktop-widgets/subsurfacewebservices.cpp index b3084da14..0d4d62bac 100644 --- a/desktop-widgets/subsurfacewebservices.cpp +++ b/desktop-widgets/subsurfacewebservices.cpp @@ -223,7 +223,7 @@ bool DivelogsDeWebServices::prepare_dives_for_divelogs(const QString &tempfile, put_format(&mb, "</site>\n</divesites>\n"); } - save_one_dive_to_mb(&mb, dive); + save_one_dive_to_mb(&mb, dive, false); if (ds) { put_format(&mb, "</divelog>\n"); diff --git a/smtk-import/smrtk2ssrfc_window.cpp b/smtk-import/smrtk2ssrfc_window.cpp index 16f2fbf6a..432ec859e 100644 --- a/smtk-import/smrtk2ssrfc_window.cpp +++ b/smtk-import/smrtk2ssrfc_window.cpp @@ -87,7 +87,7 @@ void Smrtk2ssrfcWindow::on_importButton_clicked() ui->plainTextEdit->appendPlainText(error_buf); } ui->progressBar->setValue(inputFiles.size()); - save_dives_logic(qPrintable(outputFile), false); + save_dives_logic(qPrintable(outputFile), false, false); ui->progressBar->setDisabled(true); } diff --git a/smtk-import/smtk_standalone.cpp b/smtk-import/smtk_standalone.cpp index dc152f42f..7092e26d1 100644 --- a/smtk-import/smtk_standalone.cpp +++ b/smtk-import/smtk_standalone.cpp @@ -50,7 +50,7 @@ int main(int argc, char *argv[]) smartrak_import(infile, &dive_table); } qDebug() << "\n[Writing]\n\t" << outfile << "\n"; - save_dives_logic(outfile, false); + save_dives_logic(outfile, false, false); break; } } diff --git a/tests/testparse.cpp b/tests/testparse.cpp index 59531af70..623e6cc5e 100644 --- a/tests/testparse.cpp +++ b/tests/testparse.cpp @@ -373,13 +373,13 @@ void TestParse::exportCSVDiveDetails() { parse_file(SUBSURFACE_TEST_DATA "/dives/test40.xml", &dive_table); - export_dives_xslt("testcsvexportmanual.csv", 0, 0, "xml2manualcsv.xslt"); - export_dives_xslt("testcsvexportmanualimperial.csv", 0, 1, "xml2manualcsv.xslt"); + export_dives_xslt("testcsvexportmanual.csv", 0, 0, "xml2manualcsv.xslt", false); + export_dives_xslt("testcsvexportmanualimperial.csv", 0, 1, "xml2manualcsv.xslt", false); clear_dive_file_data(); parseCSVmanual(1, "testcsvexportmanualimperial.csv"); - export_dives_xslt("testcsvexportmanual2.csv", 0, 0, "xml2manualcsv.xslt"); + export_dives_xslt("testcsvexportmanual2.csv", 0, 0, "xml2manualcsv.xslt", false); FILE_COMPARE("testcsvexportmanual2.csv", "testcsvexportmanual.csv"); @@ -422,13 +422,13 @@ void TestParse::exportCSVDiveProfile() { parse_file(SUBSURFACE_TEST_DATA "/dives/test40.xml", &dive_table); - export_dives_xslt("testcsvexportprofile.csv", 0, 0, "xml2csv.xslt"); - export_dives_xslt("testcsvexportprofileimperial.csv", 0, 1, "xml2csv.xslt"); + export_dives_xslt("testcsvexportprofile.csv", 0, 0, "xml2csv.xslt", false); + export_dives_xslt("testcsvexportprofileimperial.csv", 0, 1, "xml2csv.xslt", false); clear_dive_file_data(); parseCSVprofile(1, "testcsvexportprofileimperial.csv"); - export_dives_xslt("testcsvexportprofile2.csv", 0, 0, "xml2csv.xslt"); + export_dives_xslt("testcsvexportprofile2.csv", 0, 0, "xml2csv.xslt", false); FILE_COMPARE("testcsvexportprofile2.csv", "testcsvexportprofile.csv"); @@ -440,12 +440,12 @@ void TestParse::exportUDDF() { parse_file(SUBSURFACE_TEST_DATA "/dives/test40.xml", &dive_table); - export_dives_xslt("testuddfexport.uddf", 0, 1, "uddf-export.xslt"); + export_dives_xslt("testuddfexport.uddf", 0, 1, "uddf-export.xslt", false); clear_dive_file_data(); parse_file("testuddfexport.uddf", &dive_table); - export_dives_xslt("testuddfexport2.uddf", 0, 1, "uddf-export.xslt"); + export_dives_xslt("testuddfexport2.uddf", 0, 1, "uddf-export.xslt", false); FILE_COMPARE("testuddfexport.uddf", "testuddfexport2.uddf"); diff --git a/tests/testplan.cpp b/tests/testplan.cpp index dd62aa777..092015c58 100644 --- a/tests/testplan.cpp +++ b/tests/testplan.cpp @@ -368,7 +368,7 @@ void TestPlan::testMetric() #if DEBUG free(displayed_dive.notes); displayed_dive.notes = NULL; - save_dive(stdout, &displayed_dive); + save_dive(stdout, &displayed_dive, false); #endif // check minimum gas result @@ -409,7 +409,7 @@ void TestPlan::testImperial() #if DEBUG free(displayed_dive.notes); displayed_dive.notes = NULL; - save_dive(stdout, &displayed_dive); + save_dive(stdout, &displayed_dive, false); #endif // check minimum gas result @@ -450,7 +450,7 @@ void TestPlan::testVpmbMetric45m30minTx() #if DEBUG free(displayed_dive.notes); displayed_dive.notes = NULL; - save_dive(stdout, &displayed_dive); + save_dive(stdout, &displayed_dive, false); #endif // check minimum gas result @@ -481,7 +481,7 @@ void TestPlan::testVpmbMetric60m10minTx() #if DEBUG free(displayed_dive.notes); displayed_dive.notes = NULL; - save_dive(stdout, &displayed_dive); + save_dive(stdout, &displayed_dive, false); #endif // check minimum gas result @@ -512,7 +512,7 @@ void TestPlan::testVpmbMetric60m30minAir() #if DEBUG free(displayed_dive.notes); displayed_dive.notes = NULL; - save_dive(stdout, &displayed_dive); + save_dive(stdout, &displayed_dive, false); #endif // check minimum gas result @@ -543,7 +543,7 @@ void TestPlan::testVpmbMetric60m30minEan50() #if DEBUG free(displayed_dive.notes); displayed_dive.notes = NULL; - save_dive(stdout, &displayed_dive); + save_dive(stdout, &displayed_dive, false); #endif // check minimum gas result @@ -580,7 +580,7 @@ void TestPlan::testVpmbMetric60m30minTx() #if DEBUG free(displayed_dive.notes); displayed_dive.notes = NULL; - save_dive(stdout, &displayed_dive); + save_dive(stdout, &displayed_dive, false); #endif // check minimum gas result @@ -617,7 +617,7 @@ void TestPlan::testVpmbMetric100m60min() #if DEBUG free(displayed_dive.notes); displayed_dive.notes = NULL; - save_dive(stdout, &displayed_dive); + save_dive(stdout, &displayed_dive, false); #endif // check minimum gas result @@ -660,7 +660,7 @@ void TestPlan::testVpmbMetricMultiLevelAir() #if DEBUG free(displayed_dive.notes); displayed_dive.notes = NULL; - save_dive(stdout, &displayed_dive); + save_dive(stdout, &displayed_dive, false); #endif // check minimum gas result @@ -691,7 +691,7 @@ void TestPlan::testVpmbMetric100m10min() #if DEBUG free(displayed_dive.notes); displayed_dive.notes = NULL; - save_dive(stdout, &displayed_dive); + save_dive(stdout, &displayed_dive, false); #endif // check minimum gas result @@ -738,7 +738,7 @@ void TestPlan::testVpmbMetricRepeat() #if DEBUG free(displayed_dive.notes); displayed_dive.notes = NULL; - save_dive(stdout, &displayed_dive); + save_dive(stdout, &displayed_dive, false); #endif // check minimum gas result @@ -759,7 +759,7 @@ void TestPlan::testVpmbMetricRepeat() #if DEBUG free(displayed_dive.notes); displayed_dive.notes = NULL; - save_dive(stdout, &displayed_dive); + save_dive(stdout, &displayed_dive, false); #endif // check minimum gas result @@ -796,7 +796,7 @@ void TestPlan::testVpmbMetricRepeat() #if DEBUG free(displayed_dive.notes); displayed_dive.notes = NULL; - save_dive(stdout, &displayed_dive); + save_dive(stdout, &displayed_dive, false); #endif // check minimum gas result |