File: passwordsafe-db-remapper.pl

package info (click to toggle)
passwordsafe 1.12.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 25,980 kB
  • sloc: cpp: 67,939; ansic: 1,696; makefile: 584; perl: 459; sh: 240; xml: 210; javascript: 40
file content (207 lines) | stat: -rwxr-xr-x 5,147 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#!/usr/bin/perl
#
# passwordsafe-db-remapper v1.0.0
#
# Written by Eddy L O Jansson <eddy@klopper.net>
# Donated into the Public Domain
#
# This program will convert an exported Password Safe v3.0BETA1 database
# into a modern format that can be imported into the 3.1x series, which
# do not natively support this database format.
#
# To export from PS, use File -> Export To -> Plain text and enable '^' as
# the line delimiter. Then run the output through this program.
#
# Usage:
#  $ passwordsafe-db-remapper <exported_30b1.txt >new.txt
#
# Notes:
#  The code is a bit verbose, it was written to be easy to extend to handle
#  any future similar remappings.
#
# History
# ===========================================================================
# 2007-12-30  1.0.0  eloj  First version done.
#
# To do:
# ===========================================================================
#  * Nothing
#
use strict;
# Currently disabled since we only have one mapping and don't need the extra dependency.
#use Getopt::Long;
#use POSIX "strftime";

my $program_version = "1.0.0-20071230";

my %cfg = (
 ESCAPECHAR => '^',
 SEPARATOR => "\t",
 DEFAULT_MAPPING => "30b1",
);

my %columns = (
  0 => { NAME => 'Group/Title' },
  1 => { NAME => 'Username' },
  2 => { NAME => 'Password' },
  3 => { NAME => 'URL' },
  4 => { NAME => 'AutoType' },
  5 => { NAME => 'Created Time' },
  6 => { NAME => 'Password Modified Time' },
  7 => { NAME => 'Last Access Time' },
  8 => { NAME => 'Password Expiry Date' },
  9 => { NAME => 'Record Modified Time' },
 10 => { NAME => 'History' },
 11 => { NAME => 'Notes' },
);

# Defines a mapping from 3.0beta1 to modern format.
my %ps30b1_to_ps31x = (
  NAME => "PasswordSafe v3.0BETA1 to PasswordSafe v3.1x conversion",
  HEADER_SUB => \&modern_header,
  COLMAP => {
    0 => { COLID => 0, TRANSFORM_SUB => \&fixup_grouptitle },
    1 => { COLID => 1 },
    2 => { COLID => 2 },
    3 => { COLID => 3 },
    4 => { COLID => 4 },
    5 => { COLID => 5 },
    6 => { COLID => 11 },
  }
);

# For the user to be able to select between mappings, use a tag code.
my %mappings = (
  "30b1" => \%ps30b1_to_ps31x
);

sub output_version
{
  print "passwordsafe-db-remapper version ".$program_version."\n";
  print "Written 2007 by Eddy L O Jansson <eddy\@klopper.net>\n";
  print "This is software is donated into the PUBLIC DOMAIN.\n";
  print "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, ";
  print "to the extent permitted by law.\n";
  exit 0;
}

sub output_help
{
  print "usage: $0 [OPTIONS] <infile >outfile\n\n";

  print "optional:\n";

  print " --list             Show available mappings.\n";
  print " --mapping CODE     Which mapping to use.\n";
  print "\n";
  print " --version          Print version number and exit.\n";
  print " --help             This help text and exit.\n";
  print "\n";
  print "Go to http://gazonk.org/~eloj/ for the latest version or bug reports.\n";
  exit 0;
}

sub output_mappings
{
  print "="x65; print "\n";
  print "Code - Name\n";
  print "="x65; print "\n";
  foreach my $m (keys %mappings)
  {
    print $m." - ".$mappings{$m}->{NAME}."\n";
  }
  exit 0;
}


#
# Remove quotes and convert periods to escape character.
#
sub fixup_grouptitle
{
  my $cfg = shift;
  my $param = shift;

  # Split into group and title on first period
  my @gt = split(/\./, $param, 2);

  if( $gt[1] ) {
    $gt[1] =~ s/\"//g;    # Remove quotes
    $gt[1] =~ s/\./$cfg->{ESCAPECHAR}/g;   # Escape periods
    return $gt[0].".".$gt[1];
  } else {
    return $param;
  }
}

#
# Just a real busy way of outputting all the headers, tab separated.
#
sub modern_header
{
  my $cfg = shift;
  my $param = shift;
  my $cols = keys(%columns);

  for(my $i=0 ; $i < $cols ; ++$i)
  {
    print $columns{$i}->{NAME};
    print $cfg->{SEPARATOR} if $i < $cols-1;
  }
  print "\n";
}

#############################################################################
#
# main
#
#############################################################################

my $code = $cfg{DEFAULT_MAPPING};

#
# Handle command line options
#
#  GetOptions(
#    'mapping=s' => \$code,
#    'list' => sub { output_mappings(); },
#    'version' => sub { output_version(); },
#    'help|?' => sub { output_help(); },
#  );

my $mapping = $mappings{$code};

if( ! defined $mapping->{HEADER_SUB} )
{
  print "Error: Mapping '".$code."' seems not be defined. Try --list.\n";
  exit 1;
}

#
# With everything set up, let's start the conversion:
#

# Output header
$mapping->{HEADER_SUB}(\%cfg, $mapping);

while( my $line = <STDIN> )
{
  chomp $line;
  my @fields = split(/$cfg{SEPARATOR}/o, $line);
  my @outline;

  # For each field, we check the conversion mapping to see if, what and
  # where to output it.
  for(my $i=0 ; $i < @fields ; ++$i)
  {
    if( defined $mapping->{COLMAP}->{$i}->{COLID} )
    {
      my $s = defined $mapping->{COLMAP}->{$i}->{TRANSFORM_SUB} ?
        $mapping->{COLMAP}->{$i}->{TRANSFORM_SUB}(\%cfg, $fields[$i]) : $fields[$i];
      $outline[ $mapping->{COLMAP}->{$i}->{COLID} ] = $s;
    }
  }
  print join($cfg{SEPARATOR}, @outline)."\n";
}

exit 0;