#!/usr/bin/perl -w # Copyright (c) 2007, Perforce Software, Inc. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL PERFORCE SOFTWARE, INC. BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Encrypt a checkpoint. Only certain fields on certain records are encrypted # so that the result is a working checkpoint. For example, depot paths and # depot filenames are encrypted, but revision numbers are not. Words # (strings of uppercase and lowercase alphabetic characters) are encrypted # consistently throughout so that the result is a working checkpoint. For # example, if the first occurrence of the word "david" is encrypted to # "uZcuS", the remainder of the occurrences of the word "david" are encrypted # to "uZcuS". The "--insensitive" flag is required to correctly encrypt a # checkpoint that originated on a case-insensitive server. # # The example of encrypting "david" to "uZcuS" hints that the encryption # is more complex than a simple single character translation. If a simple # single character translation were used and "d" is translated to "u", then # "i" should translate to something other than "u". Further, a simple single # character translation would translate "d" to "u" consistently rather than # translating the first "d" to "u" and the second "d" to "S". # # For understanding the encryption algorithm used in this script, think # base 52 where each "digit" has been randomized. A word's encryption is the # base 52 representation (using the randomized "digits") of the number of # previously encrypted words having the same length as the word being # encrypted. Consider these words and their encryptions: # # david uZcuS # aaaa ZcuS # bbbb Zcul # ccccc uZcul # # The randomized "digits" for this encryption were: # # SlokPvAYdQMxDVuCherqJXnIbTfRKzHgZcGmijLUyWpOEBtFNswa # ulVSIpByKfTQUdOCescjwkAMGWPDNhJqnitLFRvYzXZbxgmaEorH # csIAbEgHvqRMTypYkKZxhaeoXUwnSCmQWVirBJfdGzOtPLNuljDF # ZyicVqYukhDeAKmvEgSBMCorITdjsFtxbwRpXQWOzPGNfalnJULH # uevPcQVsTqzFaLOmxKYwHogyflRUMSjphAtGdXkEDWrbZCnNiIBJ # # (Each execution of this script will have a different randomization # of the digits.) # # When the script starts, it has seen zero words of all lengths. The first # word encoutered, "david", has a length of five. Since there have been # zero words with a length of five previously encrypted, the result of # encrypting the word "david" is zero in the base 52 representation using the # same number of randomized "digits" as the length of the word being encrypted # (which has the desirable benefit of preserving the size of the checkpoint, # the length of the depot paths, etc.). The next word encountered, "aaaa", # is encrypted in a similar manner as "david" since there have been # zero words with a length of four previously encrypted. # # For the next word encountered, "bbbb", the encrypted result is one in the # base 52 representation using the randomized "digits", since one word with # a length of four had previously been encrypted. And finally, for "ccccc", # the encrypted result is also one in the base 52 representation using the # randomized "digits", since one word with a length of five had previously # been encrypted. # # The P4::Journal module must be installed as this script heavily uses that # module. This script is very CPU-intensive. # # Usage: # # | encryptckp.pl [--insensitive] # # where: # # is a regular file or "-" to continue the pipe # # The --insensitive option is necessary when encrypting a checkpoint # that originated on a case-insensitive server. # # Examples: # # Encrypt an uncompressed checkpoint that originated on a case-insensitive # server and save the results to an uncompressed checkpoint: # # cat customer.ckp | encryptckp.pl --insensitive encrypted.ckp # # Encrypt a compressed checkpoint that did not originate on a case-insensitive # server and save the results to a compressed checkpoint: # # cat customer.ckp.gz | gunzip | encryptckp.pl - | gzip > encrypted.ckp.gz # package EncryptCkp; use P4::Journal; our @ISA = qw( P4::Journal ); my @wordsubs; my $insensitive; my @chrs; my @letters; my @nlens; my @excepts; @excepts{ ( "any","branch","change","client","depot","default","edge","forwarding", "group","job","label","protect","p4s","replica","remote","repo","rmt", "server","spec","stream","trigger","typemap","user" ) } = ( undef ) x 19; sub new( $$ ) { my $class = shift; $insensitive = shift; my $output = shift; my $i; my $self = new P4::Journal; keys %wordsubs = 524288; for( $i = 0; $i < 26; $i++ ) { $chrs[ $i ] = chr( $i + 0x41 ); $chrs[ $i + 26 ] = chr( $i + 0x61 ); } bless( $self, $class ); open OUTPUT, ">$output" or die "Could not write to \'" . $output . "\':\n" . $!; return $self; } sub AddLen( $ ) { my $self = shift; my $ilen = shift; $letters[ $ilen ] = [ map { $_->[ 0 ] } sort { @$a[ 1 ] <=> @$b[ 1 ] } map { [ $_, rand ] } @chrs ]; $nlens[ $ilen ] = 0; } sub SubsWords( $$ ) { my $self = shift; my $raw = shift; my $case = shift; my @words; my @subs; my $isub; my $word; my $wordsub; my $len; my $nlen; my $nnlens; my $i; @words = split /([A-Za-z0-9]+)/, $raw; $#subs = $#words; $isub = 0; foreach $word ( @words ) { if( $word =~ /[A-Za-z]+/ ) { if( $case && $insensitive ) { $word = lc $word; } if( !exists $excepts{ $word } ) { $wordsub = $wordsubs{ $word }; } else { $wordsub = $word; } if( !defined $wordsub ) { $len = length $word; $nnlens = scalar @nlens; if( $len > $nnlens ) { for( $i = $nnlens; $i < $len; $i++ ) { $self->AddLen( $i ); } } $len--; while( 1 ) { $wordsub = ""; $nlen = $nlens[ $len ]; for( $i = 0; $i <= $len; $i++ ) { $wordsub = $letters[ $i ][ $nlen % 52 ] . $wordsub; $nlen = int( $nlen / 52 ); } $nlens[ $len ]++; if( !exists $excepts{ $wordsub } ) { last; } } $wordsubs{ $word } = $wordsub; } $subs[ $isub ] = $wordsub; } else { $subs[ $isub ] = $word; } $isub++; } return join "", @subs; } sub ParseRecord( $ ) { my $self = shift; my $rec = shift; my $op; my $jver; my $dbName; my $remainder; my $attr; my $name; my $address; if ( $rec->Raw() ) { ($op, $jver, $dbName, $remainder) = split " ", $rec->Raw(), 4; SWITCH: { if( !defined $dbName ) { last SWITCH; } if( !defined $rec->Raw() ) { last SWITCH; } if( $dbName eq "\@db.archive@" ) { $rec->Lbrfile( $self->SubsWords( $rec->Lbrfile(), 1 ) ); $rec->Depotfile( $self->SubsWords( $rec->Depotfile(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.archmap@" ) { $rec->Lbrfile( $self->SubsWords( $rec->Lbrfile(), 1 ) ); $rec->Depotfile( $self->SubsWords( $rec->Depotfile(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.boddate@" ) { last SWITCH; } if( $dbName eq "\@db.bodtext@" ) { $attr = $rec->Attr(); if( $attr == 103 || $attr == 105 ) { $rec->Text( $self->SubsWords( $rec->Text(), 0 ) ); } last SWITCH; } if( $dbName eq "\@db.bodtexthx@" || $dbName eq "\@db.bodtextcx@") { $attr = $rec->Type(); if( $attr == 115 ) { $rec->Key( $self->SubsWords( $rec->Key(), 0 ) ); $rec->Text( $self->SubsWords( $rec->Text(), 0 ) ); } last SWITCH; } if( $dbName eq "\@db.change@" || $dbName eq "\@db.changex@" ) { $rec->Client( $self->SubsWords( $rec->Client(), 1 ) ); $rec->User( $self->SubsWords( $rec->User(), 1 ) ); $rec->Description( $self->SubsWords( $rec->Description(), 0 ) ); $rec->Root( $self->SubsWords( $rec->Root(), 0 ) ); $rec->Importer( $self->SubsWords( $rec->Importer(), 0 ) ); last SWITCH; } # db.config is another tricky one. Some values need to be left alone. :P if( $dbName eq "\@db.config@" || $dbName eq "\@db.counters@" ) { $name = $rec->Name(); if( $name ne "change" && $name ne "job" && $name ne "jobreview" && $name ne "journal" && $name ne "logger" && $name ne "monitor" && $name ne "review" && $name ne "security" && $name ne "unicode" && $name ne "lastCheckpointAction" && $name ne "traits" && $name ne "upgrade" && $name ne "maxCommitChange" && $name !~ /^.*\..*$/ && $name !~ /^P4/i) { $rec->Name( $self->SubsWords( $name, 1 ) ); } if ( $dbName eq "\@db.config@" || $name =~ /^.*\..*$/ ) { $rec->SName( $self->SubsWords( $rec->SName(), 1 ) ); } if ( $name =~ /^P4/) { $rec->Value( $self->SubsWords( $rec->Value(), 1 ) ); } last SWITCH; } if( $dbName eq "\@db.depot@" ) { $rec->Name( $self->SubsWords( $rec->Name(), 1 ) ); if( $jver == 0 ) { $address = $rec->Address(); if( $address ne "subdir" ) { $rec->Address( $self->SubsWords( $address, 0 ) ); } } else { $rec->Extra( $self->SubsWords( $rec->Extra(), 0 ) ); } $rec->Map( $self->SubsWords( $rec->Map(), 0 ) ); last SWITCH; } if( $dbName eq "\@db.desc@" ) { $rec->Description( $self->SubsWords( $rec->Description(), 0 ) ); last SWITCH; } if( $dbName eq "\@db.domain@" ) { $rec->Name( $self->SubsWords( $rec->Name(), 1 ) ); $rec->Extra( $self->SubsWords( $rec->Extra(), 0 ) ); $rec->Mount( $self->SubsWords( $rec->Mount(), 0 ) ); $rec->Mount2( $self->SubsWords( $rec->Mount2(), 0 ) ); $rec->Mount3( $self->SubsWords( $rec->Mount3(), 0 ) ); $rec->Owner( $self->SubsWords( $rec->Owner(), 1 ) ); $rec->Description( $self->SubsWords( $rec->Description(), 0 ) ); last SWITCH; } if( $dbName eq "\@db.excl@" ) { $rec->Depotfile( $self->SubsWords( $rec->Depotfile(), 1 ) ); $rec->Client( $self->SubsWords( $rec->Client(), 1 ) ); $rec->User( $self->SubsWords( $rec->User(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.fix@" || $dbName eq "\@db.fixrev@" ) { $rec->Client( $self->SubsWords( $rec->Client(), 1 ) ); $rec->User( $self->SubsWords( $rec->User(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.graphperm@" ) { $rec->Name( $self->SubsWords( $rec->Name(), 1 ) ); $rec->Repo( $self->SubsWords( $rec->Repo(), 1 ) ); $rec->User( $self->SubsWords( $rec->User(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.group@" ) { $rec->User( $self->SubsWords( $rec->User(), 1 ) ); $rec->Group( $self->SubsWords( $rec->Group(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.groupx@" ) { $rec->Group( $self->SubsWords( $rec->Group(), 1 ) ); $rec->Ldapuserattribute( $self->SubsWords( $rec->Ldapuserattribute(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.have@" ) { $rec->Clientfile( $self->SubsWords( $rec->Clientfile(), 1 ) ); $rec->Depotfile( $self->SubsWords( $rec->Depotfile(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.integ@" ) { $rec->Tofile( $self->SubsWords( $rec->Tofile(), 1 ) ); $rec->Fromfile( $self->SubsWords( $rec->Fromfile(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.integed@" ) { $rec->Tofile( $self->SubsWords( $rec->Tofile(), 1 ) ); $rec->Fromfile( $self->SubsWords( $rec->Fromfile(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.ixdate@" ) { last SWITCH; } if( $dbName eq "\@db.ixtext@" ) { $attr = $rec->Attr(); if( $attr == 103 || $attr == 105 || $attr == 115 ) { $rec->Word( $self->SubsWords( $rec->Word(), 0 ) ); } if ( $attr == 115 ) { $rec->Value( $self->SubsWords( $rec->Word(), 0 ) ); } last SWITCH; } if( $dbName eq "\@db.ixtexthx@" ) { $rec->Word( $self->SubsWords( $rec->Word(), 0 ) ); $rec->Value( $self->SubsWords( $rec->Value(), 0 ) ); last SWITCH; } if( $dbName eq "\@db.job@" || $dbName eq "\@db.jobpend@" ) { $rec->Xuser( $self->SubsWords( $rec->Xuser(), 1 ) ); $rec->Description( $self->SubsWords( $rec->Description(), 0 ) ); last SWITCH; } if( $dbName eq "\@db.jobdesc@" ) { $rec->Xdescription( $self->SubsWords( $rec->Xdescription(), 0 ) ); last SWITCH; } if( $dbName eq "\@db.label@" ) { $rec->Name( $self->SubsWords( $rec->Name(), 1 ) ); $rec->Depotfile( $self->SubsWords( $rec->Depotfile(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.locks@" ) { $rec->Depotfile( $self->SubsWords( $rec->Depotfile(), 1 ) ); $rec->Client( $self->SubsWords( $rec->Client(), 1 ) ); $rec->User( $self->SubsWords( $rec->User(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.logger@" ) { last SWITCH; } if( $dbName eq "\@db.message@" ) { last SWITCH; } if( $dbName eq "\@db.monitor@" ) { $rec->User( $self->SubsWords( $rec->User(), 1 ) ); $rec->Args( $self->SubsWords( $rec->Args(), 1 ) ); if( $jver == 1 ) { $rec->Client( $self->SubsWords( $rec->Client(), 1 ) ); $rec->Host( $self->SubsWords( $rec->Host(), 0 ) ); $rec->App( $self->SubsWords( $rec->App(), 0 ) ); } last SWITCH; } if( $dbName eq "\@db.property@" ) { $rec->User( $self->SubsWords( $rec->User(), 1 ) ); $rec->Scope( $self->SubsWords( $rec->Scope(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.protect@" ) { $rec->User( $self->SubsWords( $rec->User(), 1 ) ); $rec->Host( $self->SubsWords( $rec->Host(), 0 ) ); $rec->Depotfile( $self->SubsWords( $rec->Depotfile(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.pubkey@" ) { $rec->User( $self->SubsWords( $rec->User(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.ref@" ) { $rec->Repo( $self->SubsWords( $rec->Repo(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.refhist@" ) { $rec->Repo( $self->SubsWords( $rec->Repo(), 1 ) ); $rec->User( $self->SubsWords( $rec->User(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.remote@" ) { $rec->Owner( $self->SubsWords( $rec->Owner(), 1 ) ); $rec->Desc( $self->SubsWords( $rec->Desc(), 1 ) ); $rec->RmtUser( $self->SubsWords( $rec->RmtUser(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.repo@" ) { $rec->Repo( $self->SubsWords( $rec->Repo(), 1 ) ); $rec->Owner( $self->SubsWords( $rec->Owner(), 1 ) ); $rec->Desc( $self->SubsWords( $rec->Desc(), 1 ) ); $rec->Branch( $self->SubsWords( $rec->Branch(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.repoview@" ) { $rec->Name( $self->SubsWords( $rec->Name(), 1 ) ); $rec->Viewfile( $self->SubsWords( $rec->Viewfile(), 1 ) ); $rec->Depotfile( $self->SubsWords( $rec->Depotfile(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.resolve@" || $dbName eq "\@db.resolvex@") { $rec->Tofile( $self->SubsWords( $rec->Tofile(), 1 ) ); $rec->Fromfile( $self->SubsWords( $rec->Fromfile(), 1 ) ); $rec->Basefile( $self->SubsWords( $rec->Basefile(), 1 ) ); $rec->Subpath( $self->SubsWords( $rec->Subpath(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.resolveg@" ) { $rec->TFile( $self->SubsWords( $rec->TFile(), 1 ) ); $rec->FFile( $self->SubsWords( $rec->FFile(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.rev@" || $dbName eq "\@db.revbx@" || $dbName eq "\@db.revdx@" || $dbName eq "\@db.revhx@" || $dbName eq "\@db.revpx@" || $dbName eq "\@db.revsh@" || $dbName eq "\@db.revsx@" || $dbName eq "\@db.revtx@" || $dbName eq "\@db.revux@" ) { $rec->Depotfile( $self->SubsWords( $rec->Depotfile(), 1 ) ); $rec->Lbrfile( $self->SubsWords( $rec->Lbrfile(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.revcx@" ) { $rec->Depotfile( $self->SubsWords( $rec->Depotfile(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.review@" ) { $rec->User( $self->SubsWords( $rec->User(), 1 ) ); $rec->Depotfile( $self->SubsWords( $rec->Depotfile(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.sendq@" ) { $rec->Depotfile( $self->SubsWords( $rec->Depotfile(), 1 ) ); $rec->Clientfile( $self->SubsWords( $rec->Clientfile(), 1 ) ); $rec->Lbrfile( $self->SubsWords( $rec->Lbrfile(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.server@" ) { $rec->Name( $self->SubsWords( $rec->Name(), 1 ) ); $rec->Desc( $self->SubsWords( $rec->Desc(), 1 ) ); $rec->Address( $self->SubsWords( $rec->Address(), 1 ) ); $rec->User( $self->SubsWords( $rec->User(), 1 ) ); $rec->ExternalAddress( $self->SubsWords( $rec->ExternalAddress(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.stream@" ) { $rec->Stream( $self->SubsWords( $rec->Stream(), 1 ) ); $rec->Parent( $self->SubsWords( $rec->Parent(), 1 ) ); $rec->Title( $self->SubsWords( $rec->Title(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.template@" ) { $rec->Name( $self->SubsWords( $rec->Name(), 1 ) ); $rec->Parent( $self->SubsWords( $rec->Parent(), 1 ) ); $rec->Path( $self->SubsWords( $rec->Path(), 1 ) ); $rec->ViewFile( $self->SubsWords( $rec->ViewFile(), 1 ) ); $rec->DepotFile( $self->SubsWords( $rec->DepotFile(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.templatesx@" ) { $rec->Shelf( $self->SubsWords( $rec->Shelf(), 1 ) ); $rec->Parent( $self->SubsWords( $rec->Parent(), 1 ) ); $rec->Path( $self->SubsWords( $rec->Path(), 1 ) ); $rec->ViewFile( $self->SubsWords( $rec->ViewFile(), 1 ) ); $rec->DepotFile( $self->SubsWords( $rec->DepotFile(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.templatewx@" ) { $rec->Client( $self->SubsWords( $rec->Client(), 1 ) ); $rec->Name( $self->SubsWords( $rec->Name(), 1 ) ); $rec->Parent( $self->SubsWords( $rec->Parent(), 1 ) ); $rec->Path( $self->SubsWords( $rec->Path(), 1 ) ); $rec->ViewFile( $self->SubsWords( $rec->ViewFile(), 1 ) ); $rec->DepotFile( $self->SubsWords( $rec->DepotFile(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.traits@" ) { $name = $rec->Name(); if( $name ne "refs" && $name ne "thumb" ) { $rec->Name( $self->SubsWords( $name, 1 ) ); } if( $name ne "refs" ) { $rec->Value( $self->SubsWords( $rec->Value(), 0 ) ); } last SWITCH; } # Triggers are tricksey beasts. For one, the action field could # "leak" proprietary data in the form of arguments, but making the # string completely unintelligible will have unpredictable results. # Perhaps a flag to just drop triggers? A "--filter" function could # allow people to drop the table(s) (likely included in a standard chk # file, otherwise they could have used p4d db dump filtering). # # Or, as I do here, I just replace the trigger with "pass". :P # @pv@ 3 @db.trigger@ 0 @zGmwk-zGmwz@ 0 @mwX-user-(BQRAzGmwn|zGmwO)@ @@ 21 @perl check_integ.pl %args% //depot/path1 //depot/path2@ if( $dbName eq "\@db.trigger@" ) { if( $jver == 0 ) { $rec->Trigger( $self->SubsWords( $rec->Trigger(), 1 ) ); } else { $rec->Name( $self->SubsWords( $rec->Name(), 1 ) ); } $attr = $rec->DepotFile(); if ( $attr =~ /^pre\-user\-.*/ || $attr =~ /^pre\-user\-.*/ ) { $rec->DepotFile( $attr ); } $rec->TriggerDepotFile( $self->SubsWords( $rec->TriggerDepotFile(), 0 ) ); $rec->Action( "pass" ); last SWITCH; } if( $dbName eq "\@db.user@" ) { $rec->User( $self->SubsWords( $rec->User(), 1 ) ); $rec->Email( $self->SubsWords( $rec->Email(), 0 ) ); $rec->Jobview( $self->SubsWords( $rec->Jobview(), 0 ) ); $rec->Fullname( $self->SubsWords( $rec->Fullname(), 0 ) ); last SWITCH; } # db.uxtext? if( $dbName eq "\@db.view@" ) { $rec->Name( $self->SubsWords( $rec->Name(), 1 ) ); $rec->Viewfile( $self->SubsWords( $rec->Viewfile(), 1 ) ); $rec->Depotfile( $self->SubsWords( $rec->Depotfile(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.working@" || $dbName eq "\@db.workingx@") { $rec->Clientfile( $self->SubsWords( $rec->Clientfile(), 1 ) ); $rec->Depotfile( $self->SubsWords( $rec->Depotfile(), 1 ) ); $rec->Client( $self->SubsWords( $rec->Client(), 1 ) ); $rec->User( $self->SubsWords( $rec->User(), 1 ) ); last SWITCH; } if( $dbName eq "\@db.workingg@" ) { $rec->CFile( $self->SubsWords( $rec->CFile(), 1 ) ); $rec->DFile( $self->SubsWords( $rec->DFile(), 1 ) ); $rec->Client( $self->SubsWords( $rec->Client(), 1 ) ); $rec->User( $self->SubsWords( $rec->User(), 1 ) ); $rec->MFile( $self->SubsWords( $rec->MFile(), 1 ) ); last SWITCH; } } } printf OUTPUT "%s\n", $rec->Raw(); } sub DESTROY { close OUTPUT; } package main; use Getopt::Long; $insensitive = 0; GetOptions( "insensitive" => \$insensitive ); my $output = shift; if (!defined $output) { die "You must supply an output file name.\n"; } my $ckp = new EncryptCkp( $insensitive, $output ); $ckp->Parse;