<?php

/*
 * Customization log file manager
 *
 * How to use:
 *
 * 1) modify the authenticate function below, if you would like to include account profile in the authentication mechanism for this script
 * 2) add working API credentials to DECRYPT_USERNAME and DECRYPT_PASSWORD contstants
 * 3) place this script in the scripts/custom directory for any site/interface
 * 4) produce log files from customizations in the site /tmp directory (with either .txt or .log file extensions)
 * 5) access logs using this script at URL: https://<site inteface domain>/cgi-bin/<inteface name>.cfg/php/custom/log_file_manager.php
 *
 * Note: Files in /tmp directory should have filenames containing dates, so that new log files are created daily from 
 *  customizations (at a minimum). Files are automatically removed from this site /tmp directory every two weeks, by timestamp.
 *
 * Disclaimer: Use this customization at your own risk. It is strongly recommended that a) log files produced do not contain sensitive
 *  data, and b) this customization only be used over https.
 *
 */

use RightNow\Connect\v1_3 as RNCPHP;

use RightNow\Connect\Crypto\v1_3 as Crypto;

if (!defined('DOCROOT')) {
    $docroot = get_cfg_var('doc_root');
    define('DOCROOT', $docroot);
}

//hard coded to allow for file downloads without the need to enter credentials
// allows for the Crypto API to be initialized, so that the actual user's credentials
// are used to authenticate downloads
//
define('DECRYPT_USERNAME', "<enter account username here>");
define('DECRYPT_PASSWORD', "<enter account password here>");

/*
 * See 'API access control and authentication' here:
 *
 * https://documentation.custhelp.com/euf/assets/devdocs/cloud22a/Connect_PHP/Default.htm
 *
 */
function authenticate($userName, $password) {
    require_once(DOCROOT . '/include/services/AgentAuthenticator.phph');
	 // use function below instead, if you want to limit users of this script by profile
    //return AgentAuthenticator::authenticateCookieOrCredentialsAndProfile($userName, $password, $agentProfile = array("Admin Profile", "Agent Profile")); // add profile specific check
    return AgentAuthenticator::authenticateCredentials($userName, $password);
}

function pass() {
    if (!empty($_POST['password'])) {
        return htmlspecialchars(trim($_POST['password']));
    }
    return '';
}

function user() {
    if (!empty($_POST['username'])) {
        return htmlspecialchars(trim($_POST['username']));
    }
    return '';
}

function viewFile($path) {
	if (file_exists($path)) {
		echo $path . ":";
		echo "<br/><br/>";
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename=' . basename($path));
        header('Expires: 0');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        header('Content-Length: ' . filesize($path));
        readfile($path);
    }
}

function downloadFile($path) {
	if (file_exists($path)) {
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename=' . basename($path));
        header('Expires: 0');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        header('Content-Length: ' . filesize($path));
        readfile($path);
    }
}

function scanTmp($dir) {
    $dircontents = array();
    if (is_dir($dir)) {
        if ($dh = opendir($dir)) {
            while (($file = readdir($dh)) !== false) {
                $dircontents[] = $file;
            }
            closedir($dh);
        }
    }
    sort($dircontents);
    return $dircontents;
}

function makeSafe($field, $mode='encrypt') {
	try {		
		$cipher = new Crypto\AES();  
		$cipher->Mode->ID =1; 
		$cipher->IV->Value = "1234567812345678";
		$cipher->KeySize->LookupName = "128_bits";
		$cipher->KeyDerivative = new Crypto\CryptoKeyDerivative();
		$cipher->KeyDerivative->Mode->ID = 2;
		$cipher->KeyDerivative->Salt = new Crypto\CryptoKeyDerivativeSalt();
		$cipher->KeyDerivative->Salt->Value = "yiuyipoipi";
		$cipher->KeyDerivative->Password = "UYIUYDSFSDFSDFPOIPOI";
		$cipher->KeyDerivative->Iteration = 1000;
		if ($mode == 'encrypt') {
			$cipher->Text = $field;
			$cipher->encrypt();
			return $cipher->EncryptedText;
		} else {
			$cipher->EncryptedText = $field;
			$cipher->decrypt();		
			return $cipher->Text;
		} 
	} catch (\Exception $e) {		
		echo "Exception: " . $e->getMessage();
	}
}

if (!empty($_GET['action']) && (trim($_GET['action']) == 'view' || trim($_GET['action']) == 'download')) {
	try {
		//authenticate with the hard-coded credentials
		// only to get to the Crypto API and decrypt the real user's credentials
		authenticate(htmlspecialchars(trim(DECRYPT_USERNAME)), htmlspecialchars(trim(DECRYPT_PASSWORD)));
		if (!authenticate(htmlspecialchars(trim(makeSafe(base64_decode($_POST['username']), 'decrypt'))), htmlspecialchars(trim(makeSafe(base64_decode($_POST['password']), 'decrypt'))))) {
			exit();
		}
		if (trim($_GET['action']) == 'view') {
		    viewFile($_GET['path']);
		} else {
		    downloadFile($_GET['path']);
		} 
		exit();
	} catch (\Exception $e) {
		echo "Exception: " . $e->getMessage();
	}
} else {
	authenticate(user(), pass());
}
?>

<!DOCTYPE html>
<html><head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Log File Manager</title>
<style>
body {font-family: "lucida grande","Segoe UI",Arial, sans-serif; font-size: 14px;width:1024;padding:1em;margin:0; }
th {font-weight: normal; color: #1F75CC; background-color: #F0F9FF; padding:.5em 1em .5em .2em;
	text-align: left;cursor:pointer;user-select: none; }
th .indicator {margin-left: 6px }
thead {border-top: 1px solid #82CFFA; border-bottom: 1px solid #96C4EA;border-left: 1px solid #E7F2FB;
	border-right: 1px solid #E7F2FB; }
a, a:visited { color:#00c; text-decoration: none }
a:hover {text-decoration: underline }
table {border-collapse: collapse;width:100%; }
td { padding:.2em 1em .2em .2em; border-bottom:1px solid #def;height:30px; font-size:12px;white-space: nowrap; }
td.first {font-size:14px;white-space: normal; }
td.empty { color:#777; font-style: italic; text-align: center;padding:3em 0; }
form { outline: none; border-width:0px; border:none; outline: 0px solid transparent; }
fieldset { outline: none; border-width:0px; border:none; outline: 0px solid transparent; }
footer {font-size:14px; color:#bbbbc5; padding:4em 0 0;text-align: left;}
</style>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
</head><body>
<table id="table"><thead><tr>
	<th>Name</th>
	<th>Date</th>
	<th>Size (bytes)</th>
	<th>&nbsp;&nbsp;&nbsp;Action</th>
</tr></thead><tbody id="list">
<?php
    $path = '/tmp/';
    $files = array();
    $keep = array("txt", "log");

    foreach (scanTmp($path) as $file) {
        $extension = pathinfo($file, PATHINFO_EXTENSION);
        if (in_array($extension, $keep)) {
            $files[$file] = filemtime($path . $file);
        }
    }
    arsort($files);
    $files = array_keys($files);
    foreach ($files as $resource) {
        $thisPath = $path . $resource;
		$user = base64_encode(makeSafe($_POST['username']));
		$pass = base64_encode(makeSafe($_POST['password']));
        $date = date("Y-m-d H:i:s", filemtime($thisPath));
        $size = filesize($thisPath);
        printf("<tr><td>%s</td>", $resource);
        printf("<td>%s</td>", $date);
        printf("<td>%s</td>", $size);
        printf("<td><form action='?path=%s&action=view' method='post' target='_blank' accept-charset='UTF-8'>
            <fieldset>
                <input type='hidden' name='submitted' id='submitted' value='1'/>
                <input type='hidden' name='username' id='username'  value='" . $user . "' />
                <input type='hidden' name='password' id='password' value='" . $pass . "' />
                <input type='submit' name='view' value='View' />
            </fieldset>
        </form>
		<form action='?path=%s&action=download' method='post' target='_blank' accept-charset='UTF-8'>
            <fieldset>
                <input type='hidden' name='submitted' id='submitted' value='1'/>
                <input type='hidden' name='username' id='username'  value='" . $user . "' />
                <input type='hidden' name='password' id='password' value='" . $pass . "' />
                <input type='submit' name='download' value='Download' />
            </fieldset>
        </form></td></tr>", $thisPath, $thisPath);
    }
?>
</tbody></table>
<footer><b>Disclaimer:</b> Use this customization at your own risk. It is strongly recommended that a) log files produced do not contain sensitive data, and b) this customization only be used over https.</footer>
</body></html>