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>
This commit is contained in:
Robert C. Helling 2018-09-10 14:47:56 +02:00 committed by Dirk Hohndel
parent adbb1488e8
commit afe363fa85
10 changed files with 114 additions and 68 deletions

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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);
}

View file

@ -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>

View file

@ -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");

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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");

View file

@ -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