Location: PHPKode > projects > ViewSVN > index.php
<?php
/** @file index.php
 * The main controller gadget. Reads config, processes user input, acts
 * accordingly and finally passes required data to templates.
 */
require('include/config.php');
require('include/libsvn.php');
if ($config['debug']) { error_reporting(E_ALL); }

$page['base_href'] = dirname($_SERVER['SCRIPT_NAME']);
if ($page['base_href'] === '/') { $page['base_href'] = ''; }

function linkauthor($author) {
	global $config;
	if (isset($config['author_link'])) {
		return "<a href=\"". sprintf($config['author_link'], urlencode($author)) ."\">$author</a>";
	}
	return $author;
}

/**
 * Make internal link to an action, heeding URL rewriting.
 * @return URL relative to server root, or viewsvn dir
 */
function makelink($dict) {
	global $config;
	global $page;
	$base = '';

	// If rewriting is enabled, embed some parameters into the URL
	if ($config['rewrite'] == 1 || $config['rewrite'] == 2) {
		if (isset($dict['do'], $dict['project'], $dict['path'])) {
			// unset the "used" parameters and append rest as parameters
			$base = $page['base_href'];

			// Internal rewriting requires "index.php" in the path;
			// everything after it is passed to PHP in PATH_INFO
			if ($config['rewrite'] == 2) {
				$base .= '/index.php';
			}

			$base .= "/$dict[do]/". rawurlencode($dict['project']) .':'. rawurlencode($dict['path']);
			if (isset($dict['rev']) && $dict['rev'] != 'HEAD') {
				$base .= "@$dict[rev]";
			}
			$base = str_replace('%2F', '/', $base);
			unset($dict['do'], $dict['project'], $dict['path'], $dict['rev']);
		}
	}

	// Rest of the parameters go into query string
	$params = array();
	foreach ($dict as $k => $v) {
		if ($k === 'rev' && $v === 'HEAD') { continue; }
		$params[] = rawurlencode($k) .'='. str_replace('%2F', '/', rawurlencode($v));
	}
	if (count($params) > 0) {
		return $base .htmlentities('?'. join('&', $params));
	} else {
		return $base;
	}
}

// ------------------------------------------------------------
// Process parameters
// ------------------------------------------------------------

if (isset($_REQUEST['do'])) { $do = $_REQUEST['do']; } else { $do = 'index'; }
if (isset($_REQUEST['project'])) { $project = $_REQUEST['project']; }
if (isset($_REQUEST['path'])) { $path = $_REQUEST['path']; }
if (isset($_REQUEST['rev'])) { $rev = $_REQUEST['rev']; }
if (isset($_REQUEST['oldrev'])) { $oldrev = $_REQUEST['oldrev']; }

// Internal rewriting ($config['rewrite'] = 2)
// /action/project:/path/@rev
if (isset($_SERVER['PATH_INFO'])) {
	$path_info = $_SERVER['PATH_INFO'];
	if (preg_match('!/([^/]*)/([^:]*):(.*?)(?:@([^@]*))?$!', $path_info, $matches) > 0) {
		$do = $matches[1];
		$project = $matches[2];
		$path = $matches[3];
		if (count($matches) > 4) {
			$rev = $matches[4];
		}
	} else {
		die("Invalid PATH_INFO");
	}
}

// could validate path (no ..'s = escaping out of svnroot)? SVN does this already.
if (isset($project) && !isset($config['projects'][$project])) { unset($project); }
if (!isset($path)) { $path = '/'; }
if (isset($rev) && $rev != 'HEAD' && !is_numeric($rev)) { unset($rev); }
if (isset($oldrev) && $oldrev != 'HEAD' && !is_numeric($oldrev)) { unset($oldrev); }
if (!isset($rev)) { $rev = 'HEAD'; }

// ------------------------------------------------------------
// Init SVN
// ------------------------------------------------------------

$svn = new SVN();
if (isset($config['svnusername']) && isset($config['svnpassword'])) {
	$svn->setAuthentication($config['svnusername'], $config['svnpassword']);
}
if (isset($config['cachedir'])) { $svn->setCacheDir($config['cachedir']); }

if (isset($config['svncommand'])) { $svn->setCommand($config['svncommand']); }
if (isset($config['svn_global_parameters'])) { $svn->setGlobalParameters($config['svn_global_parameters']); }
if (isset($project)) {
	$p = $config['projects'][$project];
	
	if (isset($p['root'])) {
		$svn->setRoot($p['root']);
	}
	elseif (isset($config['svnroot'])) {
		$svn->setRoot($config['svnroot'] .'/'. $project);
	}
	else {
		die("SVN root not configured for '$project'");
	}

	if (isset($p['username']) && isset($p['password'])) {
		$svn->setAuthentication($p['username'], $p['password']);
	}
}
if (isset($path)) {
	$svn->setPath($path);
}

// ------------------------------------------------------------
// Handle actions
// ------------------------------------------------------------
// First, we process the request we got, get necessary data etc, then set a
// template name that is included in the end to display the requested data.
// In special cases like rss and download we die() before coming out of the
// ifs.

// Information available for all templates
if (isset($project)) { $page['project'] = $project; }
$page['path'] = $path;
$page['rev'] = $rev;
$page['pathnodes'] = split('/', $path);
if (isset($project) && isset($path)) { $page['title'] = "$project:$path - ViewSVN"; }
array_shift($page['pathnodes']);
array_pop($page['pathnodes']);

// ACTION: browse
// PARAMETERS: PROJECT
// COMMANDS: ls -v (1), info (1), log (N)
if ($do == 'browse' && isset($project)) {
	if (!isset($path)) { $path = '/'; }
	$page['title'] = "$project:$path - ViewSVN";
	$page['nodes'] = $svn->listFiles(isset($rev) ? $rev : 'HEAD', true);
	
	if ($config['enable_proplist']) {
		$page['proplist'] = $svn->getProperties($rev);
		if (!strlen($page['proplist'])) {
			unset($page['proplist']);
		}
	}
	
	$template = 'browse';
}

// A: diff
// P: PROJECT, PATH, REV, OLDREV, RAW?
// C: diff
elseif ($do == 'diff' && isset($project) && isset($path) && isset($rev) && isset($oldrev)) {
	if (!$config['enable_diff']) { die('Diff has not been enabled'); }

	if (isset($_REQUEST['raw'])) {
		header("Content-type: text/plain");
		die($svn->getDiff($oldrev, $rev));
	}
	
	// Colorify added/removed/@@ lines, and link "Index:" lines
	$page['content'] = preg_replace(array(
		'/^(@@.*@@)$/m',
		'/^(-.*)$/m',
		'/^(\+.*)$/m',
		'/^Index: (.+)$/m',
		), array(
		'<span class="pos">$1</span>',
		'<span class="removed">$1</span>',
		'<span class="added">$1</span>',
		"Index: <a href=\"". str_replace('///', '/$1', makelink(array('do' => 'view', 'project' => $project, 'path' => "$path//", 'rev' => $rev))) ."\" title=\"View this file\">$1</a>",
		), 
		htmlspecialchars($svn->getDiff($oldrev, $rev)));
	$page['oldrev'] = $oldrev;
	$page['title'] = "Diff $oldrev-$rev - $project:$path - ViewSVN";

	$template = 'diff';
}

// A: download
// P: PROJECT, PATH, REV?
// C: cat
elseif ($do == 'download' && isset($project) && isset($path) && isset($rev)) {
	if (!$config['enable_download']) { die('Download has not been enabled'); }

	header('Content-type: archive/x-tar');
	header("Content-disposition: filename=".urlencode($project)."-snapshot.tar.bz2");

	echo $svn->downloadArchive($rev);
	die();
}

// A: list
// P: PROJECT, PATH, REV?
// C: ls -R
elseif ($do == 'list' && isset($project) && isset($path)) {
	if (!$config['enable_list']) { die('List has not been enabled'); }

	$page['nodes'] = $svn->listFiles($rev, false, true);

	$template = 'list';
}

// A: log
// P: PROJECT, PATH, REV?
// C: log
elseif ($do == 'log' && isset($project) && isset($path)) {
	if (!$config['enable_log']) { die('Log viewing has not been enabled'); }

	$page['title'] = 'View log';
	$page['entries'] = $svn->getLog($rev, 1, $config['log_limit']);

	$template = 'log';
}

// A: rss
// P: PROJECT, PATH
// C: log
elseif ($do == 'rss' && isset($project) && isset($path)) {
	if (!$config['enable_rss']) { die('RSS feeds have not been enabled'); }

	$page['items'] = $svn->getLog('HEAD', '1', $config['rss_limit']);
	require('templates/rss.php');
	die();
}

// A: view
// P: PROJECT, PATH, REV?, ANNOTATE?, RAW?
// C: cat
elseif ($do == 'view' && isset($project) && isset($path)) {
	$page['title'] = "$project:$path ($rev) - ViewSVN";

	if (isset($_REQUEST['raw'])) {
		header('Content-type: text/plain');
		echo $svn->getFileContents($rev);
		die();
	}

	if (isset($_REQUEST['annotate']) && $config['enable_annotate']) {
		$content = htmlspecialchars($svn->getAnnotation($rev));
		$link1 = makelink(array('do' => 'view', 'project' => $project, 'path' => $path, 'rev' => '\\2'));
		$link2 = makelink(array('do' => 'log', 'project' => $project, 'path' => $path, 'rev' => '\\2'));
		$content = preg_replace('/^( *)(\d+)/m', "\\1<a href=\"$link1\" title=\"Show file at this revision\">\\2</a> <a href=\"$link2\" title=\"View log entry for this line\">?</a>", $content);
		$page['filecontent'] = $content;
	}
	else {
		// Get file extension from current path
		$tmp = explode('.', $path);
		$ext = array_pop($tmp);
		if ($ext == 'cc' || $ext == 'hh') { $ext = 'cpp'; }

		if ($config['enable_geshi'] && strlen($ext) > 0) {
			include_once($config['geshi_path']);
			$geshi =& new GeSHi($svn->getFileContents($rev), GeSHi::get_language_name_from_extension($ext));
			$page['filecontent'] = $geshi->parse_code();
		} else {
			$page['filecontent'] = htmlspecialchars($svn->getFileContents($rev));
		}
	}

	$template = 'view';
}

// A: index
// P: -
// C: -
else {
	// if there is only one project, browse it by default
	if (count(array_keys($config['projects'])) == 1) {
		$target = array_keys($config['projects']);
		$target = array_shift($target);
		$startpath = '/';
		if (isset($config['startpath'])) { $startpath = $config['startpath']; }
		if (isset($config['projects'][$target]['startpath'])) { $startpath = $config['projects'][$target]['startpath']; }
		header("Location: http://". $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'] . "?do=browse&project=". urlencode($target) ."&path=". urlencode($startpath));
		die();
	}

	$page['title'] = 'ViewSVN - List of projects';
	$page['description'] = 'List of projects available for browsing';
	$page['projects'] = array();
	$page['keywords'] = join(', ', array_keys($config['projects']));
	foreach ($config['projects'] as $p => $v) {
		$startpath = '/';
		if (isset($config['startpath'])) { $startpath = $config['startpath']; }
		if (isset($v['startpath'])) { $startpath = $v['startpath']; }

		array_push($page['projects'], array(
			'name' => $p,
			'description' => $v['description'],
			'path' => $startpath,
		));
	}

	$template = 'projectlist';
}

// Display the requested template
require("templates/header.php");
require("templates/$template.php");
require("templates/footer.php");

Return current item: ViewSVN