Difference between revisions of "ObfuscateScript"
(→Obfuscate Script) |
m (None) |
||
Line 1: | Line 1: | ||
− | 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. | + | Sometimes users hit a bug in GnuCash that a developer can't reproduce. This bug may be triggered <span class="plainlinks">[http://www.thepiggybackrider.com/ <span style="color:black;font-weight:normal; text-decoration:none!important; background:none!important; text-decoration:none;/*CITATION*/">child carrier</span>]</span> 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. | Of course, a user's data file contains private information that he probably likes to keep private. | ||
Line 7: | Line 7: | ||
; Warning : Only use this script on a copy of your data ! | ; Warning : Only use this script on a copy of your data ! | ||
− | + | <pre>#!/usr/bin/perl | |
# gnucash-obfuscate.pl | # gnucash-obfuscate.pl | ||
Line 34: | Line 34: | ||
open DICT, $dictionary || die("Unable to open $dictionary"); | open DICT, $dictionary || die("Unable to open $dictionary"); | ||
− | my @dict = | + | my @dict = <DICT>; |
close DICT; | close DICT; | ||
Line 52: | Line 52: | ||
my $i; my $n = $elements->getLength; | my $i; my $n = $elements->getLength; | ||
− | for ($i=0; $i | + | for ($i=0; $i<$n; $i++) { |
my $text = $elements->item($i)->getFirstChild; | my $text = $elements->item($i)->getFirstChild; | ||
$text->setData(get_a_name($text->getData)); | $text->setData(get_a_name($text->getData)); | ||
Line 75: | Line 75: | ||
print STDERR "Obfuscating transaction notes.\n"; | print STDERR "Obfuscating transaction notes.\n"; | ||
my $transactions = $doc->getElementsByTagName('trn:slots'); | my $transactions = $doc->getElementsByTagName('trn:slots'); | ||
− | for (my $i=0; $i | + | for (my $i=0; $i<$transactions->getLength; $i++) { |
replace_text_element($transactions->item($i),'slot:value'); | replace_text_element($transactions->item($i),'slot:value'); | ||
} | } | ||
Line 116: | Line 116: | ||
my $elements = $doc->getElementsByTagName('trn:splits'); | my $elements = $doc->getElementsByTagName('trn:splits'); | ||
my $i; my $n = $elements->getLength; | my $i; my $n = $elements->getLength; | ||
− | for ($i=0; $i | + | for ($i=0; $i<$n; $i++) { |
my $parent = $elements->item($i); | my $parent = $elements->item($i); | ||
my $splits = $parent->getElementsByTagName('trn:split'); | my $splits = $parent->getElementsByTagName('trn:split'); | ||
Line 158: | Line 158: | ||
$doc->dispose; | $doc->dispose; | ||
− | + | </pre> |
Revision as of 20:04, 26 September 2011
Sometimes users hit a bug in GnuCash that a developer can't reproduce. This bug may be triggered child carrier 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.
- Warning
- Only use this script on a copy of your data !
<pre>#!/usr/bin/perl
- 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>