encryptckp.pl #1

  • //
  • guest/
  • robert_cowham/
  • perforce/
  • utils/
  • journal_tool/
  • encryptckp.pl
  • View
  • Commits
  • Open Download .zip Download (21 KB)
#!/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:
#
#   <pipe> | encryptckp.pl [--insensitive] <output-file>
#
# where:
#
#   <output-file> 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;
# Change User Description Committed
#1 32178 Robert Cowham journal_tool