Skip to content
Snippets Groups Projects
pastebin.php 7.73 KiB
Newer Older
<?php

/**
 * Notes :
 *	% Need to either a) install Text_Highlighter as a PEAR module properly or b) alter it so
 *	  that it can be included properly without having a Text/ directory at the same level
 *        as the index file.
 *      % Needs some form of cron job or similar to remove old entries
 *		* This would seem preferable to running a delete query every page view
 *		* The retain_until field is there and set by the script so 
 *		  the framework is there for removal.
 *		* Rather than using a cron job this could be done using a simple timestamp stored in a php
 *		  file which could be included (ie $timestamp = X, then include that and 
 *		  if($timestamp >= now()) { delete query }
 *	% Preventing XSS in User input needed
 *		* Should be handled by any User Auth
 *	% Needs Checking for Aeternus-Brand Stupidity
 * Fixed :
 *	% Problem with strtotime() not parsing PostGres timestamps
 		* set field type to timestamp(0) to remove fractional seconds
 *	% Added User Authentication using pwauth
 *		* Could still do with session handling
 *	% Frosty mentioned it wasn't using a monospace font
 *		* Simply made all text within the .hl-main block use the 
 * 		  Courier New Monospace font
 *		* Could possibly offer the user more customisation in terms of 
 * 		  how they want things displayed (necessary??)
 */


// Debugging

// Config
define('_LIST_LIMIT', 15);
// Defined so we can customise them to whatever we like
define('_BASE_PATH', 'https://'.$_SERVER['SERVER_NAME'].'/');
define('_SCRIPT_NAME', 'PasteBin/');
define('_TABLE_NAME', 'pastebin');

$smarty->assign('urifragment', '/Tools/PasteBin/');
$pburi = 'https://'.$_SERVER['SERVER_NAME'].$baseurl;
$smarty->assign('uri', $pburi.'/pb/');

// Init
$id = '';
if (is_numeric($pathlist[count($pathlist) - 1])) {
	//$id = substr($_SERVER['PATH_INFO'],1);
	//$id = preg_match('/[0-9]+/', $id)?$id:'';
	$i = count($pathlist)-1;
	$id = $pathlist[$i];
	$id = preg_match('/[0-9]+/', $id)?$id:'';
} else if (is_numeric($pathlist[count($pathlist) - 2]) && (strtolower($pathlist[count($pathlist) - 1]) == 'plain') ) {
	// Plain text
	$no_template = true;
	$id = $pathlist[count($pathlist) - 2];
	$id = preg_match('/[0-9]+/', $id)?$id:'';
	$code = $DB->GetOne('SELECT code FROM ' . _TABLE_NAME . ' WHERE  id = ?', array($id));
	header('Content-Type: text/plain');
	print html_entity_decode($code, ENT_QUOTES,'UTF-8');
	return; // Finish processing in this file
}
$code = '';
$pblang = '';

// Includes
require_once 'PEAR.php';
require_once 'Text/Highlighter.php';
require_once 'Text/Highlighter/Renderer.php';
require_once 'Text/Highlighter/Renderer/Html.php';
require_once '../lib/ArrayRenderer.php';

//yay php5.4
(new PEAR)->setErrorHandling(PEAR_ERROR_TRIGGER, E_USER_WARNING);

// Grabbed from blog.lib.php
// Returns a textual diff between two time stamps
function timeDiff($first, $second=0)
{
	if($second == 0) {
		$second = time();
	}

	$diff = max($first, $second) - min($first, $second);

	if($diff>604800) {
		$ret = round($diff/604800);
		return $ret.(($ret>1)? _(" weeks") : _(" week"));
	}
	elseif($diff>86400) {
		$ret = round($diff/86400);
		return $ret.(($ret>1)? _(" days") : _(" day"));
	}
	elseif($diff>3600) {
		$ret = round($diff/3600);
		return $ret.(($ret>1)? _(" hours") : _(" hour"));
	}
	elseif($diff>60) {
		$ret = round($diff/60);
		return $ret.(($ret>1)? _(" minutes") : _(" minute"));
	}
	elseif($diff>0) {
		return $diff.(($diff>1)? _(" seconds") : _(" second"));
	}
	else {
		return "no time";
	}
}

// Languages
$LANGUAGES = array (
	'PHP' => 'PHP',
	'CPP' => 'C/C++',
	'DIFF' => 'Diff',
	'DTD' => 'DTD',
	'HTML' => 'HTML',
	'JAVA' => 'Java',
	'JAVASCRIPT' => 'Javascript',
	'MYSQL' => 'MySQL',
	'PERL' => 'Perl',
	'PYTHON' => 'Python',
	'RUBY' => 'Ruby',
	'SQL' => 'SQL',
	'XML' => 'XML'
);

// Remove Old Pastebin Entries
// possibly some error handling needed?
$DB->Execute('DELETE FROM ' . _TABLE_NAME . ' WHERE retain_til < now()');

// Needed here?
//removeMagicQuotes($_POST);

if (isset($_POST['code'])) {
	$code = htmlentities($_POST['code'], ENT_QUOTES,'UTF-8');
	if ( isset($_POST['language']) && isset($_POST['retain'])) {
		// Add
		$pblang = strtoupper($_POST['language']);
		if (!isset($LANGUAGES[ $pblang ])) {
 			$pblang = 'NONE';
 		}
        
	
		switch($_POST['retain'][0]) {
			case 'month' :
				$retain = 2592000;
				$retainTil = date('Y/m/d H:i:s', time() + $retain);break;
			case 'week' :
				$retain = 604800; 
				$retainTil = date('Y/m/d H:i:s', time() + $retain);break;
			case 'forever' :
				$retain = null;
				$retainTil = null;break;
			case 'day' :
			default :
				$retain = 86400;
				$retainTil = date('Y/m/d H:i:s', time() + $retain);
		}
		
		if (trim($code) == '') {
			trigger_error('No Code Given', E_USER_NOTICE);
		} else if (!$session->loggedin) {
			trigger_error('You must be logged in to use this service.', E_USER_NOTICE);
		} else {
			// Additional user validation needed here
			//$retainTil = date('Y/m/d H:i:s', time() + $retain);
			$id = $DB->GetOne("SELECT nextval('pastebin_id_seq'::regclass)");
			$DB->Execute(
				'INSERT INTO ' . _TABLE_NAME . ' ( id, code, username, retain_til, language) ' .
				'VALUES (?, ?, ?, ?, ?)', 
				array( $id, $code, $session->username, $retainTil, $pblang));

			//bump user to uri of newly pasted item
			header('Status: 303 See Other');
			header("Location: $pburi/Tools/PasteBin/$id");

			$userInfo = 'Created By ' . $session->username . ' at ' . date('Y/m/d H:i');
			$smarty->assign('id', $id);
			$smarty->assign('userInfo', $userInfo);
			$smarty->assign('code', $code);
			
		}
	}
}

// List All Entries in order.
$pasteList = $DB->GetAll( 
	'SELECT id, username AS name, created AS time_diff FROM ' . _TABLE_NAME . ' ORDER BY created DESC LIMIT ' . _LIST_LIMIT );
for($i=0;$i< count($pasteList);$i++) {
	$pasteList[$i]['time_diff'] = timeDiff(strtotime($pasteList[$i]['time_diff']));
}
$smarty->assign('pasteList', $pasteList);

// Check for either display or form input
if (!empty($id) || !empty($code)) {
	// Form	
	if (empty($code)) {
		$result = $DB->GetRow('SELECT * FROM ' . _TABLE_NAME . ' WHERE  id = ?', array($id));
		//$query = db_query('SELECT * FROM ' . _TABLE_NAME . ' WHERE id = \'' . $id . '\'');
		if (!empty($result) ) {
			//$result = db_getrow($query);
			$code = $result['code'];
			$userInfo = 'Created By ' . $result['username'] . ' at ' . date('Y/m/d H:i', strtotime($result['created']));
			$pblang = $result['language'];
			// Smarty
			$smarty->assign('id', $id);
			$smarty->assign('code', $code);
			$smarty->assign('userInfo', $userInfo);
			
		} else {
			// Error
			trigger_error('Error - Code Piece not found for id - ' . $id,  E_USER_WARNING);
		}
	}
	// Check there hasn't been an error
	// Code should have been set in the if statement above, this can not become
	// an else
	if (!empty($code)) {
		// Highlight the code
		if ($pblang == 'NONE') {
			$pblang = 'HTML';
		}
		$renderer = new Text_Highlighter_Renderer_Array_dez();
		$tmpobj = new Text_Highlighter;
		$hl =& $tmpobj->factory($pblang);
		$hl->setRenderer($renderer);
		// Have to decode again here for the highlighting
		// It might be a little better if we kept the unencoded version from above
		$highlightedCode = $hl->highlight(html_entity_decode($code, ENT_QUOTES,'UTF-8'));
		$smarty->assign('highlightedCode', $highlightedCode);
	}
}
// Sort Out Languages
if(!empty($pblang) && $pblang != 'NONE') {
	$smarty->assign('selectedLanguage', array('key' => $pblang, 'lang' => $LANGUAGES[$pblang]));
	unset($LANGUAGES[$pblang]);
}
$smarty->assign('pasteLanguages', $LANGUAGES);

// Load templates etc
$smarty->assign("extra_styles", array("$baseurl/css/pastebin.css"));
$result = $smarty->fetch('pastebin.tpl');
$sidebar = $smarty->fetch('pastebin-sidebar.tpl');
$smarty->assign('title', 'PasteBin');
$smarty->assign('body', $result);
$smarty->assign('secondary',$sidebar);
?>