Difference between revisions of "ObfuscateScript"

From GnuCash
Jump to: navigation, search
m (Reverted edits by MPopp61 (talk) to last revision by Gjanssens)
(script has been moved to git)
 
(One intermediate revision by one other user not shown)
Line 5: Line 5:
 
The solution is to obfuscate the data in your data file. For the GnuCash xml data files, you can use the script by Adam Buchbinder below for that purpose.
 
The solution is to obfuscate the data in your data file. For the GnuCash xml data files, you can use the script by Adam Buchbinder below for that purpose.
  
; Warning : Only use this script on a copy of your data !
+
The script has been moved here: https://github.com/Gnucash/gnucash/blob/maint/util/obfuscate.pl
  
<pre>#!/usr/bin/perl
+
The script will read in the file, process the data, and write the output on "stdout".
 
 
# gnucash-obfuscate.pl
 
# Adam Buchbinder
 
 
 
use strict;
 
use warnings;
 
 
 
use Digest::MD5 qw(md5_hex);
 
use XML::DOM;
 
 
 
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;
 
$text->setData(get_a_name($text->getData));
 
}
 
}
 
 
 
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');
 
}
 
 
 
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;
 
}
 
 
 
# replace transaction values
 
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");
 
}
 
}
 
}
 
 
 
print STDERR "Writing output.\n";
 
print $doc->toString;
 
 
 
$doc->dispose;
 
</pre>
 

Latest revision as of 08:42, 4 February 2019

Sometimes users hit a bug in GnuCash that a developer can't reproduce. This bug may be triggered by something in the user's data file, but if the developer doesn't have access to the user's data file it can be very hard to figure out what the problem is exactly.

Of course, a user's data file contains private information that he probably likes to keep private.

The solution is to obfuscate the data in your data file. For the GnuCash xml data files, you can use the script by Adam Buchbinder below for that purpose.

The script has been moved here: https://github.com/Gnucash/gnucash/blob/maint/util/obfuscate.pl

The script will read in the file, process the data, and write the output on "stdout".