gnucash maint: Copy obfuscate script from wiki to here, with minor improvements.
Christian Stimming
cstim at code.gnucash.org
Mon Feb 4 03:33:32 EST 2019
Updated via https://github.com/Gnucash/gnucash/commit/7c767604 (commit)
from https://github.com/Gnucash/gnucash/commit/0da0f7ad (commit)
commit 7c767604ffdc595031089cc03c3c0fb6889af56b
Author: Christian Stimming <christian at cstimming.de>
Date: Mon Feb 4 09:32:51 2019 +0100
Copy obfuscate script from wiki to here, with minor improvements.
https://wiki.gnucash.org/wiki/ObfuscateScript
diff --git a/util/obfuscate.pl b/util/obfuscate.pl
new file mode 100755
index 000000000..a0d2ecf69
--- /dev/null
+++ b/util/obfuscate.pl
@@ -0,0 +1,158 @@
+#!/usr/bin/perl
+
+# Usage: gnucash-obfuscate.pl input_data.gnucash > output.gnucash
+# Adam Buchbinder
+# Christian Stimming <christian at cstimming.de>, 2019
+
+use strict;
+use warnings;
+
+use Digest::MD5 qw(md5_hex);
+use XML::DOM; # on ubuntu this requires 'libxml-dom-perl'
+
+my $dictionary = '/usr/share/dict/american-english';
+my $hex_digits = 4;
+
+unless (-f $dictionary) {
+ print STDERR "Default dictionary $dictionary not found.\n";
+ $dictionary = '/usr/share/dict/words';
+ unless (-f $dictionary) {
+ die("Cannot open dictionary $dictionary");
+ }
+}
+
+$ARGV[0] || die("Usage: $0 filename");
+(-f $ARGV[0]) || die("Unable to open $ARGV[0]");
+(-f $dictionary) || die("Dictionary file $dictionary does not exist");
+open DICT, $dictionary || die("Unable to open $dictionary");
+
+my @dict = <DICT>;
+close DICT;
+
+sub get_a_name {
+ my $scalar = shift;
+ return '' if !$scalar;
+ my $index = hex substr(md5_hex($scalar),-$hex_digits);
+ my $result = $dict[$index];
+ chop $result;
+ return $result;
+}
+
+sub replace_text_element {
+ my $doc = shift;
+ my $tag = shift;
+ my $elements = $doc->getElementsByTagName($tag);
+
+ my $i; my $n = $elements->getLength;
+ for ($i=0; $i<$n; $i++) {
+ my $text = $elements->item($i)->getFirstChild;
+ if (defined($text)) {
+ $text->setData(get_a_name($text->getData));
+ }
+ }
+}
+
+sub get_child_value {
+ my $parent = shift;
+ my $childname = shift;
+ my $index = shift;
+
+ my $return;
+ my $elements = $parent->getElementsByTagName($childname);
+ my $child;
+
+ unless (defined($index)) {
+ $child = $elements->item(0)->getFirstChild;
+ } else {
+ $child = $elements->item($index)->getFirstChild;
+ }
+ $return = $child->getData;
+ return $return;
+}
+
+sub set_child_value {
+ my $parent = shift;
+ my $childname = shift;
+ my $value = shift;
+
+ my $return;
+ my $elements = $parent->getElementsByTagName($childname);
+ my $child;
+
+ $child = $elements->item(0)->getFirstChild;
+
+ $return = $child->setData($value);
+ return $return;
+}
+
+my $parser = new XML::DOM::Parser;
+print STDERR "Parsing XML document.\n";
+my $doc = $parser->parsefile($ARGV[0]);
+
+# first, clean up strings in account names and transaction names
+print STDERR "Obfuscating account names.\n";
+replace_text_element($doc,'act:name');
+print STDERR "Obfuscating account descriptions.\n";
+replace_text_element($doc,'act:description');
+print STDERR "Obfuscating transaction descriptions.\n";
+replace_text_element($doc,'trn:description');
+print STDERR "Obfuscating check numbers.\n";
+replace_text_element($doc,'trn:num');
+print STDERR "Obfuscating split memos.\n";
+replace_text_element($doc,'split:memo');
+print STDERR "Obfuscating transaction notes.\n";
+my $transactions = $doc->getElementsByTagName('trn:slots');
+for (my $i=0; $i<$transactions->getLength; $i++) {
+ replace_text_element($transactions->item($i),'slot:value');
+}
+
+# If "1", replace money amounts, otherwise leave unchanged
+if (0) {
+ print STDERR "Obfuscating money amounts.\n";
+ my $elements = $doc->getElementsByTagName('trn:splits');
+ my $i; my $n = $elements->getLength;
+ for ($i=0; $i<$n; $i++) {
+ my $parent = $elements->item($i);
+ my $splits = $parent->getElementsByTagName('trn:split');
+ my $count = $splits->getLength;
+
+ foreach my $j (0..$count-1) {
+ my $split = $splits->item($j);
+ my $valuestring;
+ my $sum = 0;
+ my ($num,$denom);
+ if (get_child_value($split,'split:value') eq
+ get_child_value($split,'split:quantity')) {
+ $valuestring = get_child_value($split,'split:value');
+ ($num,$denom) = $valuestring =~ /(\-?\d+)\/(\d+)/;
+ $num = int rand 10*$denom; $sum += $num;
+ set_child_value($split,'split:value',"$num/$denom");
+ set_child_value($split,'split:quantity',"$num/$denom");
+ } else {
+ $valuestring = get_child_value($split,'split:value');
+ ($num,$denom) = $valuestring =~ /(\-?\d+)\/(\d+)/;
+ $num = int rand 10*$denom; $sum = $num;
+ set_child_value($split,'split:value',"$num/$denom");
+
+ $valuestring = get_child_value($split,'split:quantity');
+ ($num,$denom) = $valuestring =~ /(\-?\d+)\/(\d+)/;
+ $num = int rand 10*$denom;
+ set_child_value($split,'split:quantity',"$num/$denom");
+ }
+ # if we're on the last split, balance split:value's to 0
+ if ($j == $count-1) {
+ $valuestring = get_child_value($split,'split:value');
+ ($num,$denom) = $valuestring =~ /(\d+)\/(\d+)/;
+ $num = $sum;
+ set_child_value($split,'split:value',"$num/$denom");
+ }
+ }
+ }
+} else {
+ print STDERR "Note: The money amounts are not obfuscated.\n";
+}
+
+print STDERR "Writing output to stdout.\n";
+print $doc->toString;
+
+$doc->dispose;
Summary of changes:
util/obfuscate.pl | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 158 insertions(+)
create mode 100755 util/obfuscate.pl
More information about the gnucash-changes
mailing list