<?php

function plugin_backup_variables()
{
    $variables = array(
        'Plugin Name'   => array(
            'type'          => 'hidden',
            'description'   => '',
            'value'         => 'CE Database Backup',
        ),
        'Enabled'       => array(
            'type'          => 'yesno',
            'description'   => 'Generates a file with an SQL dump of your ClientExec database on a periodic basis, and delivers it to any of the locations set below.',
            'value'         => '0',
        ),
        'Compress file with gzip' => array(
            'type'          => 'yesno',
            'description'   => 'Only possible if you have the zlib extension in your PHP installation.',
            'value'         => '0',
            'enableIf'      => 'return extension_loaded(\'zlib\');',
        ),
        'Encryption password' => array(
            'type'          => 'text',
            'description'   => 'Enter a password if you wish to encrypt the file, or else leave empty. Only possible if you have the mcrypt extension in your PHP installation',
            'value'         => '',
            'enableIf'      => 'return extension_loaded(\'mcrypt\');',
        ),
        'Deliver to remote FTP or SFTP account' => array(
            'type'          => 'text',
            'description'   => 'To send the file to a remote FTP or SFTP account enter the host and your credentials in the format <b>ftp://username:password@host.com/subdirectory</b> for FTP<br>or<br><b>sftp://username:password@host.com/subdirectory</b> for SFTP<br>SFTP is only possible if you have the ssh2 extension in your PHP installation',
            'value'         => '',
        ),
        'Deliver to local directory' => array(
            'type'          => 'text',
            'description'   => 'To save the file in a local directory accessible and writable by the web server, enter it\'s full path here.',
            'value'         => '',
        ),
        'Deliver to E-mail address' => array(
            'type'          => 'text',
            'description'   => 'To send the file as an E-mail attachment, enter the address here.',
            'value'         => '',
        ),
        'Run schedule - Minute'  => array(
            'type'          => 'text',
            'description'   => 'Enter number, range, list or steps',
            'value'         => '30',
            'helpid'        => '8',
        ),
        'Run schedule - Hour'  => array(
            'type'          => 'text',
            'description'   => 'Enter number, range, list or steps',
            'value'         => '01',
        ),
        'Run schedule - Day'  => array(
            'type'          => 'text',
            'description'   => 'Enter number, range, list or steps',
            'value'         => '*',
        ),
        'Run schedule - Month'  => array(
            'type'          => 'text',
            'description'   => 'Enter number, range, list or steps',
            'value'         => '*',
        ),
        'Run schedule - Day of the week'  => array(
            'type'          => 'text',
            'description'   => 'Enter number in range 0-7 (0 is Sunday) or a 3 letter shortcut (e.g. sun)',
            'value'         => '*',
        ),
    );

    return $variables;
}

function plugin_backup_execute()
{
    global $gSettingsArray;

    $messages = array();

    $fileName = "backup_" . $GLOBALS['database'] . "_" . date('Y_m_d_H_i') . ".sql";

    // use references to save memory
    $sql = '';
    _plugin_backup_getSQL($sql);
    if ($gSettingsArray['plugin_backup_Compress file with gzip']) {
        $fileName .= '.gz';
        if ($message = _plugin_backup_gzip($sql, $fileName)) {
            $messages[] = $message;
        }
    }

    if ($gSettingsArray['plugin_backup_Encryption password']) {
        $fileName .= '.enc';
        if ($message = _plugin_backup_encrypt($sql, $gSettingsArray['plugin_backup_Encryption password'])) {
            $messages[] = $message;
        }
    }

    if ($gSettingsArray['plugin_backup_Deliver to remote FTP or SFTP account']) {
        $messages[] = _plugin_backup_sendFTP($sql, $fileName, $gSettingsArray['plugin_backup_Deliver to remote FTP or SFTP account']);
    }

    if ($gSettingsArray['plugin_backup_Deliver to local directory']) {
        $messages[] = _plugin_backup_sendLocal($sql, $fileName, $gSettingsArray['plugin_backup_Deliver to local directory']);
    }

    if ($gSettingsArray['plugin_backup_Deliver to E-mail address']) {
        $messages[] = _plugin_backup_sendEmail($sql, $fileName, $gSettingsArray['plugin_backup_Deliver to E-mail address']);
    }

    return $messages;
}

function plugin_backup_output()
{
    $output = "<a href=\"#\" onclick=\"window.open('index.php?fuse=".cADMIN."&action=".cADMIN_DECRYPT_SQLDUMP."', 'decryptFile', 'width=400,height=200')\" style=\"font-weight:bold\">"
             .lang('Click here to decrypt files')
             ."</a>";

    return $output;
}

function plugin_backup_dashboard()
{
}

// this is a non-standard plugin function. Don't use it anywhere else.
function plugin_backup_popup()
{
    global $tpl;

    if (!extension_loaded('mcrypt')) {
        return;
    }

    $tpl->define(array('backup_decrypt' => 'views/admin/backup_decrypt.tpl'));
    $tpl->setKey('DECRYPT_FUSE', cADMIN);
    $tpl->setKey('DECRYPT_ACTION', cADMIN_DECRYPT_SQLDUMP);
    $tpl->parse('output', 'backup_decrypt');

    return $tpl->fetch('output');   
}

// this is a non-standard plugin function. Don't use it anywhere else.
function plugin_backup_decrypt()
{
    global $gSettingsArray;

    if (!extension_loaded('mcrypt')) {
        die(lang('Error: you don\'t have the mcrypt extension enabled'));
    }

    if (!$td = mcrypt_module_open('tripledes', '', 'ecb', '')) {
        die(lang('Error: cannot initialize encryption with the triple DES algorithm in CFB mode'));
    }

    // iv is ignored in ecb mode, but I need to provide one anyway
    $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
    mcrypt_generic_init($td, $gSettingsArray['plugin_backup_Encryption password'], $iv);
    $sql = mdecrypt_generic($td, file_get_contents($_FILES['file']['tmp_name']));
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);

    _plugin_backup_downloadFile($sql);
}


// PRIVATE FUNCTIONS
function _plugin_backup_getSQL(&$sql)
{
	$sql .= file_get_contents(dirname(__FILE__).'/../../../upgrade/sql/clientexec_schema.sql');
    $result1 = $GLOBALS['db']->query('SHOW TABLES');
    while ($row1 = $result1->fetch()) {
        $sql .= "--\n-- Dumping data for table `{$row1[0]}`\n--\n\n";
        $result2 = $GLOBALS['db']->query("SELECT * FROM {$row1[0]}");
        while ($row2 = $result2->fetch(MYSQL_NUM)) {
            for ($i = 0; $i < count($row2); $i++) {
                $row2[$i] = $GLOBALS['db']->escape_string($row2[$i]);
            }
            $values = implode("', '", $row2);
            $sql .= "INSERT INTO `{$row1[0]}` VALUES('$values');\n";
        }
        $sql .= "\n\n";
    }
}

function _plugin_backup_gzip(&$sql, $fileName)
{
    // maximum compression. Make it smaller if you're having performance problems
    $compressionLevel = 9;

    if (!extension_loaded('zlib')) {
        return new Error_CE(8488, lang('Error: attempted to compress SQL dump file without having the zlib extension enabled'));
    }

    if (!$sql = gzencode($sql, $compressionLevel)) {
        return new Error_CE(8489, lang('Error: Couldn\'t gzip SQL dump file'));
    }
}

function _plugin_backup_encrypt(&$sql, $password)
{
    if (!extension_loaded('zlib')) {
        return new Error_CE(8489, lang('Error: attempted to encrypt SQL dump file without having the mcrypt extension enabled'));
    }

    if (!$td = mcrypt_module_open('tripledes', '', 'ecb', '')) {
        return new Error_CE(8490, lang('Error: cannot initialize encryption with the triple DES algorithm in ECB mode'));
    }

    // iv is ignored in ecb mode, but I need to provide one anyway
    $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
    mcrypt_generic_init($td, $password, $iv);
    $sql = mcrypt_generic($td, $sql);
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);
}

// we don't use a reference for $sql here because the ftp class might change the data
function _plugin_backup_sendFTP($sql, $fileName, $host)
{
    require_once 'plugins/services/backup/ftp_class.php';

    list($login, $password, $domain, $directory) = _plugin_backup_getFTPvars($host);

    if (strpos($host, 'ftp://') === 0) {
        $ftp = new ftp();
        if (!$ftp->setServer($domain)) {
            $ftp->quit();
            return new Error_CE(8491, lang('Error: error setting FTP server'));
        }
        if (!$ftp->connect()) {
            return new Error_CE(8492, lang('Error: can\'t connect to FTP server'));
        }
        if (!$ftp->login($login, $password)) {
            $ftp->quit();
            return new Error_CE(8493, lang('Error: authentication with FTP server failed'));
        }
        $ftp->setType(FTP_AUTOASCII);
        $ftp->passive(false);
    
        if ($directory) {
            $ftp->chdir($directory);
        }
    
        if (false !== $ftp->put($fileName, $sql)) {
            return lang('SQL dump file successfuly uploaded to FTP server: '.$fileName);
        } else {
            $ftp->quit();
            return new Error_CE(8494, lang('Error: ftp file uploading failed'));
        }
    } else if (strpos($host, 'sftp://') === 0) {
    	if(!function_exists('ssh2_connect')) {
    	    return new Error_CE(8495, lang('ssh2 extension not found in your PHP installation'));
    	}
        $connection = @ssh2_connect($domain, 22);
        if($connection == false) {
            return new Error_CE(8496, lang('Conection to %s failed using SFTP. No SSH server listening?', $domain));
        }
        $result = @ssh2_auth_password($connection, $login, $password);

        if($result == false) {
            return new Error_CE(8497, lang('Authentication Failure - Username/Password not accepted'));
        }
        $sftp = @ssh2_sftp($connection);
        $dir = "ssh2.sftp://$sftp/".$directory;

        $stream = @fopen("$dir/$fileName", 'w');
        if (!$stream) {
            return new Error_CE(8498, lang('Unable to create file on remote server'));
        }
        if(@fwrite($stream, $sql) === FALSE) {
            return new Error_CE(8499, lang('Cannot write to file (%s)', $fileName));
        }
        @fclose($stream);
        return lang('SQL dump file successfuly uploaded to SFTP server: '.$fileName);
    }
}

function _plugin_backup_sendLocal(&$sql, $fileName, $dir)
{
    $dir = _plugin_backup_stripDirSlash($dir);

    if (!@is_dir($dir)) {
        return new Error_CE(8494, lang('Error: local directory to deploy SQL dump file is not accessible'));
    }

    if (!@is_writable($dir)) {
        return new Error_CE(8494, lang('Error: local directory to deploy SQL dump file is not writable'));
    }

    if (!$fp = @fopen("$dir/$fileName", 'wb')) {
        return new Error_CE(8495, lang('Error: couldn\'t create file'));
    }
    if (!fwrite($fp, $sql)) {
        return new Error_CE(8496, lang('Error: couldn\'t write to new SQL dump file'));
    }
    fclose($fp);

    return lang('SQL dump file successfully written:')."$dir/$fileName";
}

function _plugin_backup_sendEmail(&$sql, $fileName, $email)
{
    global $gSettingsArray;

    require_once 'common/mailfunctions.php';
    if (!mailMessageEmail('',
                          $gSettingsArray['Support E-mail'],
                          'ClientExec Backup Service',
                          $email,
                          '',
                          lang('%s attached',$fileName),
                          3,
                          false,
                          $sql,
                          $fileName))
    {
        return new Error_CE(8501, lang('Error: couldn\'t send Email with SQL dump file'));
    }

    return lang('SQL dump file successfuly sent by E-mail: '.$fileName);
}

function _plugin_backup_downloadFile(&$sql)
{
    header('content-disposition: attachment; filename='.$_FILES['file']['name']);
    header('content-type: application/x-download');
    header('content-length: '.strlen($sql));
    echo $sql;
    exit;
}

function _plugin_backup_stripDirSlash($dir)
{
    if ($dir{strlen($dir)-1} == '/') {
        $dir = substr($dir, 0, strlen($dir)-1);
    }

    return $dir;
}

function _plugin_backup_getFTPVars($host)
{
    if (strpos($host, 'ftp://') === 0) {
        $host = substr($host, 6);
    } else if (strpos($host, 'sftp://') === 0) {
        $host = substr($host, 7);
    }

    $host = _plugin_backup_stripDirSlash($host);
    $loginpassword = substr($host, 0, strrpos($host, '@'));
    list($login, $password) = explode(':', $loginpassword);

    $domain = substr($host, strrpos($host, '@') + 1);
    if (($position = strpos($domain, '/')) === false) {
        $directory = false;
    } else {
        $directory = substr($domain, $position);
        $domain = substr($domain, 0, $position);
    }

    return array($login, $password, $domain, $directory);
}

?>
