#!/usr/bin/perl

# cpanel - cPanel/Gallery/Coppermine/mysql_normalized_dump.pl Copyright(c) 2013 cPanel, Inc.
#                                                            All rights Reserved.
# copyright@cpanel.net                                         http://cpanel.net
# This code is subject to the cPanel license. Unauthorized copying is prohibited

use strict;
use warnings;

use lib '../../../lib';

use Getopt::Long;
use MySQLDump::Regexp qw($IPv4_re $email_re);
use MySQLDump::Filter::OptimizeInsert;

my ( $username, $password, $database );
my $table_prefix = 'cpg15x_';
my $output       = 'dump.mysql';
GetOptions(
    'help' => \&printHelp,

    'username=s'     => \$username,
    'password=s'     => \$password,
    'db|database=s'  => \$database,
    'table-prefix=s' => \$table_prefix,
    'output=s'       => \$output,
);

# Ensure required data is provided.
die "Username not specified" unless $username;
die "Database not specified" unless $database;

# Open (create or truncate) output file and print header line.
open my $fh, '>', $output or die "Cannot open file '$output': $!";
print $fh "USE [% cpm %];\n\n";

# Create the output filter.
my $filter = MySQLDump::Filter::OptimizeInsert->new($fh);

if ( !$password ) {
    $password = '';
    print "Enter MySQL password for user '$username'\n";
}

# Dump the MySQL database (using mysqldump) and normalize any known values
# to make diffing easier.
my @cmd = ( 'mysqldump', '-h', 'localhost', '-u', $username, "-p$password", $database, '--skip-extended-insert' );
open my $pipe, '-|', @cmd or die "Cannot dump MySQL database contents: $!";
while (<$pipe>) {

    # Normalize the values and then print them to the file

    # Clean up header comments to minimize the diff noise.
    s/(?<=^-- Host: localhost    Database: )\Q$database\E/[% cpm %]/;

    # Change all table names to use [% table_prefix %].  Some column names may also
    # contain the table_prefix.  Since column names are usually preceeded by a non-word,
    # like a comma or empty spaces, and table names are usually preceeded with a word -
    # or more precisely, a command - we do a zero-width lookback to mimimize errors.
    s/(?<=\w `)\Q$table_prefix\E(?=\w)/[% table_prefix %]_/;

    if (m/^INSERT INTO `\[% table_prefix %\]_config`/) {

        # Normalize the install path.
        s/(?<=\('ecards_more_pic_target',')[^']*(?='\))/[% url_to_install %]/;

        # Normalize the gallery information.
        s/(?<=\('gallery_description',')[^']*(?='\))/[% input_2gallery_description %]/;
        s/(?<=\('gallery_name',')[^']*(?='\))/[% input_1gallery_name %]/;

        # Generate a random site token.
        s/(?<=\('site_token',)'[0-9a-fA-F]{32}'(?=\))/MD5(RAND())/;

        # Zero out the cleanup values.
        s/(?<=\('guest_token_cleanup',')\d+(?='\))/0/;
        s/(?<=\('session_cleanup',')\d+(?='\))/0/;

        # Normalize admin's email address.
        s/(?<=\('gallery_admin_email',')[^']*(?='\))/[% email %]/;

        # Normalize the ImageMagick path.
        s/(?<=\('impath',')[^']*(?='\))/[% cm_imagemagickpath %]/;
    }

    if (m/^INSERT INTO `\[% table_prefix %\]_users`/) {

        # Normalize the password field; limited to the _users table for safety
        s/(?<=')[0-9a-f]{32}(?=')/[% password_md5_hex %]/i;

        # Normalize the admin's email address; limited to the _users table for safety
        s/(?<=')$email_re(?=')/[% email %]/g;

        # Make an attempt to replace the username; be careful to ensure the table
        # format has not changed by checking both the username and its position
        # (relative to the password).
        s/(?<=,')\Q$username\E(?=','\[% password_md5_hex %\]')/[% username %]/;
    }

    # Normalize the time.
    s/(?<=,)'\d{4,}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}'/NOW()/g;

    # We don't care about any previous messages; remove them entirely.
    next if m/^INSERT INTO `\[% table_prefix %\]_temp_messages` VALUES/;

    # Remove any current sessions.
    next if m/^INSERT INTO `\[% table_prefix %\]_sessions` VALUES/;

    # Remove any test values.
    next if m/^INSERT INTO `\[% table_prefix %\]_albums` VALUES/;
    next if m/^INSERT INTO `\[% table_prefix %\]_pictures` VALUES/;

    $filter->print($_);
}

close $pipe or warn "Cannot close pipe: $!";
close $fh   or warn "Cannot close file '$output': $!";

exit 0;

sub printHelp {
    print <<EOH;
Usage: $0 -u <username> [OPTIONS]

Options:
   -u <username>  MySQL username (required).
   -p <password>  MySQL password.  If not provided, user will be prompted.
   -d <database>  MySQL database to dump (required).
   -t <prefix>    Table prefix used (defaults to '$table_prefix').
   -o <file>      Output file (defaults to 'dump.mysql').
EOH
}
