Difference between revisions of "ObfuscateScript"

From GnuCash
Jump to: navigation, search
(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
+
&lt;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 = <DICT>;
+
my @dict = &lt;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<$n; $i++) {
+
for ($i=0; $i&lt;$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<$transactions->getLength; $i++) {
+
for (my $i=0; $i&lt;$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<$n; $i++) {
+
for ($i=0; $i&lt;$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>
+
&lt;/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

  1. gnucash-obfuscate.pl
  2. 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]);

  1. 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; }

  1. 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>