Bump version
Bump version

file:a/README -> file:b/README
--- a/README
+++ b/README
@@ -79,3 +79,47 @@
 If you want to edit the text header that appears above the project list on the
 home page, edit templates/hometext.tpl.
 
+
+[Caching]
+
+To turn on caching, set the 'cache' config item to true.  Gitphp will cache
+every page's output, including plaintext output and binary output such as
+blobs and snapshots, for the number of seconds specified in the
+'cachelifetime' config key.
+The 'cacheexpire' key is recommended for most users.  With this option on,
+gitphp will attempt to keep the cache in sync by automatically expiring any
+cached pages that are older than the most recent commit, on any branch.
+It is a slight performance hit to make this check, but the performance hit
+is tiny compared to the gain you get from turning on caching.  It will
+avoid situations where users are getting a cached version of a page that
+isn't up to date and doesn't reflect the most recent commit, or worse,
+pages that have been cached at different times and show data from both
+before and after a commit (eg page 1 of the shortlog shows the most recent
+commit but page 1 of the log was cached a while ago and doesn't show the
+most recent commit).
+However, if your project is so active that commits are constantly coming in
+and invalidating the cache, rendering it useless, it would be better to
+turn cache expiration off and just set a really short cache lifetime of
+a few seconds.  In other words:
+
+Most users:
+* Set 'cacheexpire' to TRUE
+* Set 'cachelifetime' high, 3600 seconds (1 hour) or more.  -1 means
+  cache forever
+
+Extremely active projects, with commits every few seconds, or advanced
+users that know exactly how often commits come in and want to save
+the performance of the expiration check:
+* Set 'cacheexpire' to FALSE
+* Set 'cachelifetime' low, between 5-10 seconds.
+
+If you ever run into problems with your cache not syncing correctly, or
+showing out of date information, you can use the 'expire' action to force
+expiration of all cache.  This action is not linked anywhere because it
+is not supposed to be run by users, it's more of an administrative function.
+To use it, you want to set a=expire.  So, for example, you would visit this
+address in a browser (obviously with the correct path to your gitphp
+index.php):
+
+http://yourserver.com/gitphp/index.php?a=expire
+

--- a/config/gitphp.conf.php.example
+++ b/config/gitphp.conf.php.example
@@ -202,9 +202,32 @@
  * relatively high - 3600 seconds (1 hour) or even longer.
  * -1 means no timeout.
  * If you have turned cacheexpire off because of too many
- * cache expirations, set this low, like 3-5 seconds.
+ * cache expirations, set this low (5-10 seconds).
  */
 $gitphp_conf['cachelifetime'] = 3600;
+
+/*
+ * cloneurl
+ * Sets the base clone url to display for a project.
+ * This is the publicly-accessible url of the projectroot
+ * that gets prepended to the project path to create the clone
+ * url.  It can be any format, for example:
+ *
+ * http://server.com/
+ * ssh://server.com/git/
+ * git://server.com/gitprojects/
+ * (don't forget trailing slash)
+ * 
+ * If left blank/commented, no clone url will display.
+ */
+//$gitphp_conf['cloneurl'] = "http://localhost/git/";
+
+/*
+ * pushurl
+ * Sets the base push url to display for a project.
+ * Works the same as cloneurl.
+ */
+//$gitphp_conf['pushurl'] = "ssh://localhost/git/";
 
 /*
  * git_projects

--- a/include/display.git_commit.php
+++ b/include/display.git_commit.php
@@ -56,7 +56,7 @@
 		$tpl->assign("difftreesize",count($difftree)+1);
 		$difftreelines = array();
 		foreach ($difftree as $i => $line) {
-			if (ereg("^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$",$line,$regs)) {
+			if (preg_match("/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$/",$line,$regs)) {
 				$difftreeline = array();
 				$difftreeline["from_mode"] = $regs[1];
 				$difftreeline["to_mode"] = $regs[2];

--- a/include/display.git_commitdiff.php
+++ b/include/display.git_commitdiff.php
@@ -41,7 +41,7 @@
 		$tpl->assign("comment",$co['comment']);
 		$difftreelines = array();
 		foreach ($difftree as $i => $line) {
-			if (ereg("^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$",$line,$regs)) {
+			if (preg_match("/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$/",$line,$regs)) {
 				$difftreeline = array();
 				$difftreeline["from_mode"] = $regs[1];
 				$difftreeline["to_mode"] = $regs[2];

--- a/include/display.git_commitdiff_plain.php
+++ b/include/display.git_commitdiff_plain.php
@@ -12,7 +12,7 @@
  require_once('util.script_url.php');
  require_once('gitutil.git_read_commit.php');
  require_once('gitutil.git_diff_tree.php');
- require_once('gitutil.git_rev_list.php');
+ require_once('gitutil.git_read_revlist.php');
  require_once('gitutil.read_info_ref.php');
  require_once('gitutil.git_diff.php');
 
@@ -37,14 +37,12 @@
 		$diffout = git_diff_tree($projectroot . $project, $hash_parent . " " . $hash);
 		$difftree = explode("\n",$diffout);
 		$refs = read_info_ref($projectroot . $project,"tags");
-		$listout = git_rev_list($projectroot . $project, "HEAD");
-		$tok = strtok($listout,"\n");
-		while ($tok !== false) {
-			if (isset($refs[$tok]))
-				$tagname = $refs[$tok];
-			if ($tok == $hash)
+		$listout = git_read_revlist($projectroot . $project, "HEAD");
+		foreach ($listout as $i => $rev) {
+			if (isset($refs[$rev]))
+				$tagname = $refs[$rev];
+			if ($rev == $hash)
 				break;
-			$tok = strtok("\n");
 		}
 		$ad = date_str($co['author_epoch'],$co['author_tz']);
 		$tpl->assign("from",$co['author']);
@@ -56,7 +54,7 @@
 		$tpl->assign("comment",$co['comment']);
 		$diffs = array();
 		foreach ($difftree as $i => $line) {
-			if (ereg("^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$",$line,$regs)) {
+			if (preg_match("/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$/",$line,$regs)) {
 				if ($regs[5] == "A")
 					$diffs[] = git_diff($projectroot . $project, null, "/dev/null", $regs[4], "b/" . $regs[6]);
 				else if ($regs[5] == "D")

--- a/include/display.git_history.php
+++ b/include/display.git_history.php
@@ -36,9 +36,9 @@
 		$lines = explode("\n", $cmdout);
 		$historylines = array();
 		foreach ($lines as $i => $line) {
-			if (ereg("^([0-9a-fA-F]{40})",$line,$regs))
+			if (preg_match("/^([0-9a-fA-F]{40})/",$line,$regs))
 				$commit = $regs[1];
-			else if (ereg(":([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$",$line,$regs) && isset($commit)) {
+			else if (preg_match("/:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)\t(.*)$/",$line,$regs) && isset($commit)) {
 					$historyline = array();
 					$co = git_read_commit($projectroot . $project, $commit);
 					$historyline["agestringage"] = $co['age_string_age'];

--- a/include/display.git_log.php
+++ b/include/display.git_log.php
@@ -45,7 +45,7 @@
 
 		$commitlines = array();
 		$commitcount = min(100,$revlistcount);
-		for ($i = 0; $i < $commitcount; $i++) {
+		for ($i = 0; $i < $commitcount; ++$i) {
 			$commit = $revlist[$i];
 			if (isset($commit) && strlen($commit) > 1) {
 				$commitline = array();

--- a/include/display.git_rss.php
+++ b/include/display.git_rss.php
@@ -28,7 +28,8 @@
 		$tpl->assign("self",script_url());
 
 		$commitlines = array();
-		for ($i = 0; $i <= count($revlist); $i++) {
+		$revlistcount = count($revlist);
+		for ($i = 0; $i < $revlistcount; ++$i) {
 			$commit = $revlist[$i];
 			$co = git_read_commit($projectroot . $project, $commit);
 			if (($i >= 20) && ((time() - $co['committer_epoch']) > 48*60*60))
@@ -38,7 +39,7 @@
 			$diffout = git_diff_tree($projectroot . $project, $co['parent'] . " " . $co['id']);
 			$tok = strtok($diffout,"\n");
 			while ($tok !== false) {
-				if (ereg("^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$",$tok,$regs))
+				if (preg_match("/^:([0-7]{6}) ([0-7]{6}) ([0-9a-fA-F]{40}) ([0-9a-fA-F]{40}) (.)([0-9]{0,3})\t(.*)$/",$tok,$regs))
 					$difftree[] = $regs[7];
 				$tok = strtok("\n");
 			}

--- a/include/display.git_search.php
+++ b/include/display.git_search.php
@@ -10,7 +10,7 @@
 require_once('defs.constants.php');
 require_once('util.highlight.php');
 require_once('gitutil.git_read_commit.php');
-require_once('gitutil.git_rev_list.php');
+require_once('gitutil.git_read_revlist.php');
 require_once('display.git_message.php');
 
 function git_search($projectroot, $project, $hash, $search, $searchtype, $page = 0)
@@ -37,7 +37,7 @@
 
 		$co = git_read_commit($projectroot . $project, $hash);
 
-		$revlist = explode("\n",trim(git_rev_list($projectroot . $project, $hash, 101, ($page * 100), FALSE, FALSE, $searchtype, $search)));
+		$revlist = git_read_revlist($projectroot . $project, $hash, 101, ($page * 100), FALSE, FALSE, $searchtype, $search);
 		if (count($revlist) < 1 || (strlen($revlist[0]) < 1)) {
 			git_message("No matches for '" . $search . "'.", FALSE, TRUE);
 			return;
@@ -56,7 +56,7 @@
 
 		$commitlines = array();
 		$commitcount = min(100,$revlistcount);
-		for ($i = 0; $i < $commitcount; $i++) {
+		for ($i = 0; $i < $commitcount; ++$i) {
 			$commit = $revlist[$i];
 			if (strlen(trim($commit)) > 0) {
 				$commitline = array();

--- a/include/display.git_search_files.php
+++ b/include/display.git_search_files.php
@@ -88,7 +88,7 @@
 					$filesearchline["matches"] = $matches;
 			}
 			$filesearchlines[] = $filesearchline;
-			$i++;
+			++$i;
 			if ($i >= 100)
 				break;
 		}

--- a/include/display.git_shortlog.php
+++ b/include/display.git_shortlog.php
@@ -39,7 +39,7 @@
 
 		$commitlines = array();
 		$commitcount = min(100,count($revlist));
-		for ($i = 0; $i < $commitcount; $i++) {
+		for ($i = 0; $i < $commitcount; ++$i) {
 			$commit = $revlist[$i];
 			if (strlen(trim($commit)) > 0) {
 				$commitline = array();

--- a/include/display.git_summary.php
+++ b/include/display.git_summary.php
@@ -18,7 +18,7 @@
 
 function git_summary($projectroot,$project)
 {
-	global $tpl;
+	global $tpl,$gitphp_conf;
 
 	$cachekey = sha1($project);
 
@@ -33,6 +33,10 @@
 		$tpl->assign("description",$descr);
 		$tpl->assign("owner",$owner);
 		$tpl->assign("lastchange",$commitdate['rfc2822']);
+		if (isset($gitphp_conf['cloneurl']))
+			$tpl->assign('cloneurl', $gitphp_conf['cloneurl'] . $project);
+		if (isset($gitphp_conf['pushurl']))
+			$tpl->assign('pushurl', $gitphp_conf['pushurl'] . $project);
 		$revlist = git_read_revlist($projectroot . $project, $head, 17);
 		foreach ($revlist as $i => $rev) {
 			$revdata = array();

--- a/include/display.git_tree.php
+++ b/include/display.git_tree.php
@@ -50,7 +50,7 @@
 		$treelines = array();
 		$tok = strtok($lsout,"\0");
 		while ($tok !== false) {
-			if (ereg("^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$",$tok,$regs)) {
+			if (preg_match("/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$/",$tok,$regs)) {
 				$treeline = array();
 				$treeline["filemode"] = mode_str($regs[1]);
 				$treeline["type"] = $regs[2];

--- a/include/gitutil.git_exec_nix.php
+++ b/include/gitutil.git_exec_nix.php
@@ -10,7 +10,10 @@
  function git_exec_nix($project, $command)
  {
  	global $gitphp_conf;
-	$cmd = $gitphp_conf['gitbin'] . " --git-dir=" . $project . " " . $command;
+	$cmd = $gitphp_conf['gitbin'];
+	if (isset($project) && (strlen($project) > 0))
+		$cmd .= " --git-dir=" . $project;
+	$cmd .= " " . $command;
 	return shell_exec($cmd);
  }
 

--- a/include/gitutil.git_exec_win.php
+++ b/include/gitutil.git_exec_win.php
@@ -10,7 +10,10 @@
 function git_exec_win($project, $command)
 {
 	global $gitphp_conf;
-	$cmd = $gitphp_conf['gitbin'] . " --git-dir=" . $project . " " . $command;
+	$cmd = $gitphp_conf['gitbin'];
+	if (isset($project) && (strlen($project) > 0))
+		$cmd .= " --git-dir=" . $project;
+	$cmd .= " " . $command;
 	return shell_exec($cmd);
 }
 

--- a/include/gitutil.git_filesearch.php
+++ b/include/gitutil.git_filesearch.php
@@ -21,9 +21,9 @@
 	$lines = explode("\n",$grepout);
 	foreach ($lines as $j => $line) {
 		if ($case)
-			$ret = ereg("^([^:]+):([^:]+):(.*" . quotemeta($search) . ".*)",$line,$regs);
+			$ret = preg_match("/^([^:]+):([^:]+):(.*" . quotemeta($search) . ".*)/",$line,$regs);
 		else
-			$ret = eregi("^([^:]+):([^:]+):(.*" . quotemeta($search) . ".*)",$line,$regs);
+			$ret = preg_match(("/^([^:]+):([^:]+):(.*" . quotemeta($search) . ".*)/i",$line,$regs);
 		if ($ret) {
 			$fname = trim($regs[2]);
 			if (!isset($matches[$fname])) {
@@ -40,16 +40,16 @@
 	 $lsout = git_ls_tree($project, $hash, false, true);
 	 $entries = explode("\n",$lsout);
 	 foreach ($entries as $j => $line) {
-		$ret = ereg("^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)",$line,$regs);
+		$ret = preg_match("/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)/",$line,$regs);
 		$fname = trim($regs[4]);
 		if (isset($matches[$fname])) {
 			$matches[$fname]['hash'] = $regs[3];
 			$matches[$fname]['type'] = $regs[2];
 		} else {
 			if ($case)
-				$ret = ereg("^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.*" . quotemeta($search) . "[^/]*)$",$line,$regs);
+				$ret = preg_match("/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.*" . quotemeta($search) . "[^/]*)$/",$line,$regs);
 			else
-				$ret = eregi("^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.*" . quotemeta($search) . "[^/]*)$",$line,$regs);
+				$ret = preg_match("/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.*" . quotemeta($search) . "[^/]*)$/i",$line,$regs);
 			if ($ret) {
 				$fname = trim($regs[4]);
 				$matches[$fname] = array();
@@ -73,7 +73,7 @@
 		foreach ($matches as $i => $val) {
 			if ($index > $count)
 				unset($matches[$i]);
-			$index++;
+			++$index;
 		}
 	}
 

--- a/include/gitutil.git_get_hash_by_path.php
+++ b/include/gitutil.git_get_hash_by_path.php
@@ -18,7 +18,7 @@
 		$lsout = git_ls_tree($project, $tree);
 		$entries = explode("\n",$lsout);
 		foreach ($entries as $j => $line) {
-			if (ereg("^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$",$line,$regs)) {
+			if (preg_match("/^([0-9]+) (.+) ([0-9a-fA-F]{40})\t(.+)$/",$line,$regs)) {
 				if ($regs[4] == $part) {
 					if ($i == ($partcount)-1)
 						return $regs[3];

--- a/include/gitutil.git_read_commit.php
+++ b/include/gitutil.git_read_commit.php
@@ -9,13 +9,12 @@
 
  require_once('defs.constants.php');
  require_once('util.age_string.php');
- require_once('gitutil.git_rev_list.php');
+ require_once('gitutil.git_read_revlist.php');
 
 function git_read_commit($proj,$head)
 {
-	$revlist = git_rev_list($proj,$head,1,NULL,TRUE,TRUE);
-	$lines = explode("\n",$revlist);
-	if (!($lines[0]) || !ereg("^[0-9a-fA-F]{40}",$lines[0]))
+	$lines = git_read_revlist($proj,$head,1,NULL,TRUE,TRUE);
+	if (!($lines[0]) || !preg_match("/^[0-9a-fA-F]{40}/",$lines[0]))
 		return null;
 	$commit = array();
 	$tok = strtok($lines[0]," ");
@@ -31,25 +30,25 @@
 		$commit['parent'] = $parents[0];
 	$comment = array();
 	foreach ($lines as $i => $line) {
-		if (ereg("^tree ([0-9a-fA-F]{40})$",$line,$regs))
+		if (preg_match("/^tree ([0-9a-fA-F]{40})$/",$line,$regs))
 			$commit['tree'] = $regs[1];
-		else if (ereg("^author (.*) ([0-9]+) (.*)$",$line,$regs)) {
+		else if (preg_match("/^author (.*) ([0-9]+) (.*)$/",$line,$regs)) {
 			$commit['author'] = $regs[1];
 			$commit['author_epoch'] = $regs[2];
 			$commit['author_tz'] = $regs[3];
-			if (ereg("^([^<]+) <",$commit['author'],$r))
+			if (preg_match("/^([^<]+) </",$commit['author'],$r))
 				$commit['author_name'] = $r[1];
 			else
 				$commit['author_name'] = $commit['author'];
-		} else if (ereg("^committer (.*) ([0-9]+) (.*)$",$line,$regs)) {
+		} else if (preg_match("/^committer (.*) ([0-9]+) (.*)$/",$line,$regs)) {
 			$commit['committer'] = $regs[1];
 			$commit['committer_epoch'] = $regs[2];
 			$commit['committer_tz'] = $regs[3];
 			$commit['committer_name'] = $commit['committer'];
-			$commit['committer_name'] = ereg_replace(" <.*","",$commit['committer_name']);
+			$commit['committer_name'] = preg_replace("/ <.*/","",$commit['committer_name']);
 		} else {
 			$trimmed = trim($line);
-			if ((strlen($trimmed) > 0) && !ereg("^[0-9a-fA-F]{40}",$trimmed) && !ereg("^parent [0-9a-fA-F]{40}",$trimmed)) {
+			if ((strlen($trimmed) > 0) && !preg_match("/^[0-9a-fA-F]{40}/",$trimmed) && !preg_match("/^parent [0-9a-fA-F]{40}/",$trimmed)) {
 				if (!isset($commit['title'])) {
 					$commit['title'] = $trimmed;
 					if (strlen($trimmed) > GITPHP_TRIM_LENGTH)

--- /dev/null
+++ b/include/gitutil.git_read_packed_refs.php
@@ -1,1 +1,38 @@
+<?php
+/*
+ *  gitutil.git_read_packed_refs.php
+ *  gitphp: a PHP git repository browser
+ *  Component: Git utility - read packed refs
+ *
+ *  Copyright (C) 2009 Christopher Han <xiphux@gmail.com>
+ */
 
+ require_once('gitutil.git_read_hash.php');
+
+function git_read_packed_refs($projectroot, $project, $refdir)
+{
+	if (!is_file($projectroot . $project . '/packed-refs'))
+		return null;
+
+	$refs = array();
+        $refs = explode("\n",git_read_hash($projectroot . $project . "/" . 'packed-refs'));
+	$reflist = array();
+
+	$dirlen = strlen($refdir);
+
+	foreach ($refs as $i) {
+		if (preg_match('/^([0-9a-f]{40}) (.+)$/i', trim($i), $regs)) {
+			if (strncmp($refdir, $regs[2], $dirlen) === 0) {
+				$regs[2] = substr($regs[2], $dirlen+1);
+				$refobj = git_read_ref($projectroot, $project, $regs[1], $regs[2]);
+				if (isset($refobj))
+					$reflist[] = $refobj;
+			}
+		}
+        }
+
+	return $reflist;
+}
+
+?>
+

--- a/include/gitutil.git_read_projects.php
+++ b/include/gitutil.git_read_projects.php
@@ -37,7 +37,7 @@
 				$projects = git_recurse_projects($projectroot);
 				$len = count($projects);
 				$cut = strlen($projectroot);
-				for ($i = 0; $i < $len; $i++) {
+				for ($i = 0; $i < $len; ++$i) {
 					$p = substr($projects[$i],$cut + 1);
 					if ($projdata)
 						$projects[$i] = git_project_info($projectroot, $p);

--- /dev/null
+++ b/include/gitutil.git_read_ref.php
@@ -1,1 +1,60 @@
+<?php
+/*
+ *  gitutil.git_read_ref.php
+ *  gitphp: A PHP git repository browser
+ *  Component: Git utility - read single ref
+ *
+ *  Copyright (C) 2009 Christopher Han <xiphux@gmail.com>
+ */
 
+ require_once('util.age_string.php');
+ require_once('gitutil.git_get_type.php');
+ require_once('gitutil.git_read_tag.php');
+ require_once('gitutil.git_read_commit.php');
+
+ function git_read_ref($projectroot, $project, $ref_id, $ref_file)
+ {
+	$type = git_get_type($projectroot . $project, $ref_id);
+
+	if (!$type)
+		return null;
+
+	$ref_item = array();
+	$ref_item['type'] = $type;
+	$ref_item['id'] = $ref_id;
+	$ref_item['epoch'] = 0;
+	$ref_item['age_string'] = "unknown";
+
+	if ($type == "tag") {
+		$tag = git_read_tag($projectroot . $project, $ref_id);
+		$ref_item['comment'] = $tag['comment'];
+		if ($tag['type'] == "commit") {
+			$co = git_read_commit($projectroot . $project, $tag['object']);
+			$ref_item['epoch'] = $co['committer_epoch'];
+			$ref_item['age_string'] = $co['age_string'];
+			$ref_item['age'] = $co['age'];
+		} else if (isset($tag['epoch'])) {
+			$age = time() - $tag['epoch'];
+			$ref_item['epoch'] = $tag['epoch'];
+			$ref_item['age_string'] = age_string($age);
+			$ref_item['age'] = $age;
+		}
+		$ref_item['reftype'] = $tag['type'];
+		$ref_item['name'] = $tag['name'];
+		$ref_item['refid'] = $tag['object'];
+	} else if ($type == "commit") {
+		$co = git_read_commit($projectroot . $project, $ref_id);
+		$ref_item['reftype'] = "commit";
+		$ref_item['name'] = $ref_file;
+		$ref_item['title'] = $co['title'];
+		$ref_item['refid'] = $ref_id;
+		$ref_item['epoch'] = $co['committer_epoch'];
+		$ref_item['age_string'] = $co['age_string'];
+		$ref_item['age'] = $co['age'];
+	}
+
+	return $ref_item;
+ }
+
+?>
+

--- a/include/gitutil.git_read_refs.php
+++ b/include/gitutil.git_read_refs.php
@@ -7,12 +7,10 @@
  *  Copyright (C) 2008 Christopher Han <xiphux@gmail.com>
  */
 
- require_once('util.age_string.php');
  require_once('util.epochcmp.php');
- require_once('gitutil.git_get_type.php');
  require_once('gitutil.git_read_hash.php');
- require_once('gitutil.git_read_tag.php');
- require_once('gitutil.git_read_commit.php');
+ require_once('gitutil.git_read_ref.php');
+ require_once('gitutil.git_read_packed_refs.php');
 
 function git_read_refs($projectroot,$project,$refdir)
 {
@@ -40,44 +38,26 @@
 	$reflist = array();
 	foreach ($refs as $i => $ref_file) {
 		$ref_id = git_read_hash($projectroot . $project . "/" . $refdir . "/" . $ref_file);
-		$type = git_get_type($projectroot . $project, $ref_id);
-		if ($type) {
-			$ref_item = array();
-			$ref_item['type'] = $type;
-			$ref_item['id'] = $ref_id;
-			$ref_item['epoch'] = 0;
-			$ref_item['age_string'] = "unknown";
+		$refobj = git_read_ref($projectroot, $project, $ref_id, $ref_file);
+		if (isset($refobj))
+			$reflist[] = $refobj;
+	}
 
-			if ($type == "tag") {
-				$tag = git_read_tag($projectroot . $project, $ref_id);
-				$ref_item['comment'] = $tag['comment'];
-				if ($tag['type'] == "commit") {
-					$co = git_read_commit($projectroot . $project, $tag['object']);
-					$ref_item['epoch'] = $co['committer_epoch'];
-					$ref_item['age_string'] = $co['age_string'];
-					$ref_item['age'] = $co['age'];
-				} else if (isset($tag['epoch'])) {
-					$age = time() - $tag['epoch'];
-					$ref_item['epoch'] = $tag['epoch'];
-					$ref_item['age_string'] = age_string($age);
-					$ref_item['age'] = $age;
+	$packedrefs = git_read_packed_refs($projectroot, $project, $refdir);
+	if (isset($packedrefs) && count($packedrefs) > 0) {
+		foreach ($packedrefs as $packedref) {
+			$found = false;
+			foreach ($reflist as $ref) {
+				if (strcmp($ref["name"], $packedref["name"]) === 0) {
+					$found = true;
+					break;
 				}
-				$ref_item['reftype'] = $tag['type'];
-				$ref_item['name'] = $tag['name'];
-				$ref_item['refid'] = $tag['object'];
-			} else if ($type == "commit") {
-				$co = git_read_commit($projectroot . $project, $ref_id);
-				$ref_item['reftype'] = "commit";
-				$ref_item['name'] = $ref_file;
-				$ref_item['title'] = $co['title'];
-				$ref_item['refid'] = $ref_id;
-				$ref_item['epoch'] = $co['committer_epoch'];
-				$ref_item['age_string'] = $co['age_string'];
-				$ref_item['age'] = $co['age'];
 			}
-			$reflist[] = $ref_item;
+			if (!$found)
+				$reflist[] = $packedref;
 		}
 	}
+
 	usort($reflist,"epochcmp");
 	return $reflist;
 }

--- a/include/gitutil.git_read_revlist.php
+++ b/include/gitutil.git_read_revlist.php
@@ -8,11 +8,39 @@
  */
 
  require_once('gitutil.git_rev_list.php');
+ require_once('gitutil.git_version.php');
 
-function git_read_revlist($proj,$head,$count,$skip = NULL)
+function git_read_revlist($proj,$head,$count = NULL,$skip = NULL,$header = FALSE,$parents = FALSE,$greptype = NULL, $search = NULL)
 {
-	$revs = trim(git_rev_list($proj,$head,$count, $skip));
+	$passedskip = $skip;
+	$passedcount = $count;
+	$canskip = true;
+
+	if (isset($skip) && ($skip > 0)) {
+		$version = git_version();
+		if (isset($version) && (strlen($version) > 0)) {
+			$splitver = explode(".",$version);
+
+			/* Skip only appears in git >= 1.5.0 */
+			if (($splitver[0] < 1) || (($splitver[0] == 1) && ($splitver[1] < 5))) {
+				$canskip = false;
+				$passedskip = null;
+				$passedcount += $skip;
+			}
+		}
+	}
+
+	$revs = trim(git_rev_list($proj,$head, $passedcount, $passedskip, $header, $parents, $greptype, $search));
 	$revlist = explode("\n",$revs);
+
+	if ((!$canskip) && ($skip > 0)) {
+		$tmp = array();
+		$revcount = count($revlist);
+		for ($i = $skip; $i < $revcount; ++$i)
+			$tmp[] = $revlist[$i];
+		return $tmp;
+	}
+
 	return $revlist;
 }
 

--- a/include/gitutil.git_read_tag.php
+++ b/include/gitutil.git_read_tag.php
@@ -17,13 +17,13 @@
 	$comment = array();
 	$tok = strtok($tagout,"\n");
 	while ($tok !== false) {
-		if (ereg("^object ([0-9a-fA-F]{40})$",$tok,$regs))
+		if (preg_match("/^object ([0-9a-fA-F]{40})$/",$tok,$regs))
 			$tag['object'] = $regs[1];
-		else if (ereg("^type (.+)$",$tok,$regs))
+		else if (preg_match("/^type (.+)$/",$tok,$regs))
 			$tag['type'] = $regs[1];
-		else if (ereg("^tag (.+)$",$tok,$regs))
+		else if (preg_match("/^tag (.+)$/",$tok,$regs))
 			$tag['name'] = $regs[1];
-		else if (ereg("^tagger (.*) ([0-9]+) (.*)$",$tok,$regs)) {
+		else if (preg_match("/^tagger (.*) ([0-9]+) (.*)$/",$tok,$regs)) {
 			$tag['author'] = $regs[1];
 			$tag['epoch'] = $regs[2];
 			$tag['tz'] = $regs[3];

--- /dev/null
+++ b/include/gitutil.git_version.php
@@ -1,1 +1,21 @@
+<?php
+/*
+ *  gitutil.git_version.php
+ *  gitphp: A PHP git repository browser
+ *  Component: Git utility - version
+ *
+ *  Copyright (C) 2009 Christopher Han <xiphux@gmail.com>
+ */
 
+ require_once('gitutil.git_exec.php');
+
+ function git_version()
+ {
+ 	$verstr = explode(" ",git_exec(null, "--version"));
+	if (($verstr[0] == "git") && ($verstr[1] == "version"))
+		return $verstr[2];
+	return null;
+ }
+
+?>
+

--- a/include/gitutil.read_info_ref.php
+++ b/include/gitutil.read_info_ref.php
@@ -17,7 +17,7 @@
 	$showrefs = git_exec($project, $cmd);
 	$lines = explode("\n",$showrefs);
 	foreach ($lines as $no => $line) {
-		if (ereg("^([0-9a-fA-F]{40}) .*" . $type . "/([^\^]+)",$line,$regs)) {
+		if (preg_match("`^([0-9a-fA-F]{40}) .*" . $type . "/([^\^]+)`",$line,$regs)) {
 			if (isset($refs[$regs[1]]))
 				$refs[$regs[1]] .= " / " . $regs[2];
 			else

--- a/include/util.date_str.php
+++ b/include/util.date_str.php
@@ -17,7 +17,7 @@
 	$date['month'] = date("M",$epoch);
 	$date['rfc2822'] = date("r",$epoch);
 	$date['mday-time'] = date("d M H:i",$epoch);
-	if (ereg("^([+\-][0-9][0-9])([0-9][0-9])$",$tz,$regs)) {
+	if (preg_match("/^([+\-][0-9][0-9])([0-9][0-9])$/",$tz,$regs)) {
 		$local = $epoch + ((((int)$regs[1]) + ($regs[2]/60)) * 3600);
 		$date['hour_local'] = date("H",$local);
 		$date['minute_local'] = date("i",$local);

--- a/include/util.highlight.php
+++ b/include/util.highlight.php
@@ -9,7 +9,7 @@
 
 function highlight($haystack, $needle, $highlightclass, $trimlen = NULL, $escape = false)
 {
-	if (eregi("(.*)(" . quotemeta($needle) . ")(.*)",$haystack,$regs)) {
+	if (preg_match("/(.*)(" . quotemeta($needle) . ")(.*)/i",$haystack,$regs)) {
 		if (isset($trimlen) && ($trimlen > 0)) {
 			$linelen = strlen($regs[0]);
 			if ($linelen > $trimlen) {

--- a/include/version.php
+++ b/include/version.php
@@ -7,7 +7,7 @@
  *  Copyright (C) 2008 Christopher Han <xiphux@gmail.com>
  */
 
- $gitphp_version = "0.0.7";
+ $gitphp_version = "0.1.0";
  $gitphp_appstring = "gitphp $gitphp_version";
 
 ?>

file:a/index.php -> file:b/index.php
--- a/index.php
+++ b/index.php
@@ -22,13 +22,24 @@
   */
  require_once('config/gitphp.conf.php');
 
+ $project = null;
+
+ if (isset($_GET['p'])) {
+ 	$fullpath = realpath($gitphp_conf['projectroot'] . $_GET['p']);
+	$realprojroot = realpath($gitphp_conf['projectroot']);
+	$pathpiece = substr($fullpath, 0, strlen($realprojroot));
+	if (strcmp($pathpiece, $realprojroot) === 0) {
+		$project = str_replace(chr(0), '', $_GET['p']);
+	}
+ }
+
  $extraoutput = FALSE;
 
  /*
   * Instantiate Smarty
   */
  require_once($gitphp_conf['smarty_prefix'] . "Smarty.class.php");
- $tpl =& new Smarty;
+ $tpl = new Smarty;
  if ((!isset($_GET['a'])) || (
      	($_GET['a'] != "commitdiff_plain") &&
      	($_GET['a'] != "blob_plain") &&
@@ -51,14 +62,22 @@
  }
 
 /*
+ * Development
+ */
+ if (!(isset($gitphp_conf['dev']) && $gitphp_conf['dev'])) {
+ 	$tpl->compile_check = false;
+ }
+
+/*
  * Caching
  */
  if ($gitphp_conf['cache']) {
  	$tpl->caching = 2;
-	$tpl->cache_lifetime = $gitphp_conf['cachelifetime'];
-	if ($gitphp_conf['cacheexpire']) {
+	if (isset($gitphp_conf['cachelifetime']))
+		$tpl->cache_lifetime = $gitphp_conf['cachelifetime'];
+	if (!(isset($gitphp_conf['cacheexpire']) && ($gitphp_conf['cacheexpire'] === FALSE))) {
 		require_once('include/cache.cache_expire.php');
-		cache_expire($gitphp_conf['projectroot'], (isset($_GET['p']) ? $_GET['p'] : null), $git_projects);
+		cache_expire($gitphp_conf['projectroot'], $project, (isset($git_projects) ? $git_projects : null));
 	}
  }
 
@@ -68,11 +87,11 @@
  $tpl->assign("stylesheet",$gitphp_conf['stylesheet']);
  $tpl->assign("version",$gitphp_version);
  $tpl->assign("pagetitle",$gitphp_conf['title']);
- if (isset($_GET['p'])) {
+ if ($project) {
 	$tpl->assign("validproject",TRUE);
-	$tpl->assign("project",$_GET['p']);
+	$tpl->assign("project",$project);
 	require_once('include/gitutil.git_project_descr.php');
-	$tpl->assign("projectdescription",git_project_descr($gitphp_conf['projectroot'],$_GET['p']));
+	$tpl->assign("projectdescription",git_project_descr($gitphp_conf['projectroot'],$project));
 	if (isset($_GET['a'])) {
 		$tpl->assign("action",$_GET['a']);
 		$tpl->assign("validaction", TRUE);
@@ -105,97 +124,97 @@
  } else if (isset($_GET['a']) && $_GET['a'] == "project_index") {
 	require_once('include/display.git_project_index.php');
 	git_project_index($gitphp_conf['projectroot'],$git_projects);
- } else if (isset($_GET['p'])) {
- 	if (!is_dir($gitphp_conf['projectroot'] . $_GET['p'])) {
+ } else if ($project) {
+ 	if (!is_dir($gitphp_conf['projectroot'] . $project)) {
 		$tpl->assign("validproject",FALSE);
 		require_once('include/display.git_message.php');
 		git_message("No such directory",TRUE);
-	} else if (!is_file($gitphp_conf['projectroot'] . $_GET['p'] . "/HEAD")) {
+	} else if (!is_file($gitphp_conf['projectroot'] . $project . "/HEAD")) {
 		$tpl->assign("validproject",FALSE);
 		require_once('include/display.git_message.php');
 		git_message("No such project",TRUE);
 	} else {
 		if (!isset($_GET['a'])) {
 			require_once('include/display.git_summary.php');
-			git_summary($gitphp_conf['projectroot'],$_GET['p']);
+			git_summary($gitphp_conf['projectroot'],$project);
 		} else {
 			switch ($_GET['a']) {
 				case "summary":
 					require_once('include/display.git_summary.php');
-					git_summary($gitphp_conf['projectroot'],$_GET['p']);
+					git_summary($gitphp_conf['projectroot'],$project);
 					break;
 				case "tree":
 					require_once('include/display.git_tree.php');
-					git_tree($gitphp_conf['projectroot'], $_GET['p'], (isset($_GET['h']) ? $_GET['h'] : NULL), (isset($_GET['f']) ? $_GET['f'] : NULL), (isset($_GET['hb']) ? $_GET['hb'] : NULL));
+					git_tree($gitphp_conf['projectroot'], $project, (isset($_GET['h']) ? $_GET['h'] : NULL), (isset($_GET['f']) ? $_GET['f'] : NULL), (isset($_GET['hb']) ? $_GET['hb'] : NULL));
 					break;
 				case "shortlog":
 					require_once('include/display.git_shortlog.php');
-					git_shortlog($gitphp_conf['projectroot'],$_GET['p'],(isset($_GET['h']) ? $_GET['h'] : NULL), (isset($_GET['pg']) ? $_GET['pg'] : NULL));
+					git_shortlog($gitphp_conf['projectroot'],$project,(isset($_GET['h']) ? $_GET['h'] : NULL), (isset($_GET['pg']) ? $_GET['pg'] : NULL));
 					break;
 				case "log":
 					require_once('include/display.git_log.php');
-					git_log($gitphp_conf['projectroot'],$_GET['p'], (isset($_GET['h']) ? $_GET['h'] : NULL), (isset($_GET['pg']) ? $_GET['pg'] : NULL));
+					git_log($gitphp_conf['projectroot'],$project, (isset($_GET['h']) ? $_GET['h'] : NULL), (isset($_GET['pg']) ? $_GET['pg'] : NULL));
 					break;
 				case "commit":
 					require_once('include/display.git_commit.php');
-					git_commit($gitphp_conf['projectroot'],$_GET['p'],$_GET['h']);
+					git_commit($gitphp_conf['projectroot'],$project,$_GET['h']);
 					break;
 				case "commitdiff":
 					require_once('include/display.git_commitdiff.php');
-					git_commitdiff($gitphp_conf['projectroot'],$_GET['p'],$_GET['h'], (isset($_GET['hp']) ? $_GET['hp'] : NULL));
+					git_commitdiff($gitphp_conf['projectroot'],$project,$_GET['h'], (isset($_GET['hp']) ? $_GET['hp'] : NULL));
 					break;
 				case "commitdiff_plain":
 					require_once('include/display.git_commitdiff_plain.php');
-					git_commitdiff_plain($gitphp_conf['projectroot'],$_GET['p'],$_GET['h'],(isset($_GET['hp']) ? $_GET['hp'] : NULL));
+					git_commitdiff_plain($gitphp_conf['projectroot'],$project,$_GET['h'],(isset($_GET['hp']) ? $_GET['hp'] : NULL));
 					break;
 				case "heads":
 					require_once('include/display.git_heads.php');
-					git_heads($gitphp_conf['projectroot'],$_GET['p']);
+					git_heads($gitphp_conf['projectroot'],$project);
 					break;
 				case "tags":
 					require_once('include/display.git_tags.php');
-					git_tags($gitphp_conf['projectroot'],$_GET['p']);
+					git_tags($gitphp_conf['projectroot'],$project);
 					break;
 				case "rss":
 					require_once('include/display.git_rss.php');
-					git_rss($gitphp_conf['projectroot'],$_GET['p']);
+					git_rss($gitphp_conf['projectroot'],$project);
 					break;
 				case "blob":
 					require_once('include/display.git_blob.php');
-					git_blob($gitphp_conf['projectroot'],$_GET['p'], (isset($_GET['h']) ? $_GET['h'] : NULL), (isset($_GET['f']) ? $_GET['f'] : NULL), (isset($_GET['hb']) ? $_GET['hb'] : NULL));
+					git_blob($gitphp_conf['projectroot'],$project, (isset($_GET['h']) ? $_GET['h'] : NULL), (isset($_GET['f']) ? $_GET['f'] : NULL), (isset($_GET['hb']) ? $_GET['hb'] : NULL));
 					break;
 				case "blob_plain":
 					require_once('include/display.git_blob_plain.php');
-					git_blob_plain($gitphp_conf['projectroot'],$_GET['p'],$_GET['h'],(isset($_GET['f']) ? $_GET['f'] : NULL));
+					git_blob_plain($gitphp_conf['projectroot'],$project,$_GET['h'],(isset($_GET['f']) ? $_GET['f'] : NULL));
 					break;
 				case "blobdiff":
 					require_once('include/display.git_blobdiff.php');
-					git_blobdiff($gitphp_conf['projectroot'],$_GET['p'],$_GET['h'],$_GET['hb'],$_GET['hp'],(isset($_GET['f']) ? $_GET['f'] : NULL));
+					git_blobdiff($gitphp_conf['projectroot'],$project,$_GET['h'],$_GET['hb'],$_GET['hp'],(isset($_GET['f']) ? $_GET['f'] : NULL));
 					break;
 				case "blobdiff_plain":
 					require_once('include/display.git_blobdiff_plain.php');
-					git_blobdiff_plain($gitphp_conf['projectroot'],$_GET['p'],$_GET['h'],$_GET['hb'],$_GET['hp'], (isset($_GET['f']) ? $_GET['f'] : NULL));
+					git_blobdiff_plain($gitphp_conf['projectroot'],$project,$_GET['h'],$_GET['hb'],$_GET['hp'], (isset($_GET['f']) ? $_GET['f'] : NULL));
 					break;
 				case "snapshot":
 					require_once('include/display.git_snapshot.php');
-					git_snapshot($gitphp_conf['projectroot'],$_GET['p'], (isset($_GET['h']) ? $_GET['h'] : NULL));
+					git_snapshot($gitphp_conf['projectroot'],$project, (isset($_GET['h']) ? $_GET['h'] : NULL));
 					break;
 				case "history":
 					require_once('include/display.git_history.php');
-					git_history($gitphp_conf['projectroot'],$_GET['p'], (isset($_GET['h']) ? $_GET['h'] : NULL),$_GET['f']);
+					git_history($gitphp_conf['projectroot'],$project, (isset($_GET['h']) ? $_GET['h'] : NULL),$_GET['f']);
 					break;
 				case "search":
 					if (isset($_GET['st']) && ($_GET['st'] == 'file')) {
 						require_once('include/display.git_search_files.php');
-						git_search_files($gitphp_conf['projectroot'],$_GET['p'],(isset($_GET['h']) ? $_GET['h'] : NULL),(isset($_GET['s']) ? $_GET['s'] : NULL),(isset($_GET['pg']) ? $_GET['pg'] : 0));
+						git_search_files($gitphp_conf['projectroot'],$project,(isset($_GET['h']) ? $_GET['h'] : NULL),(isset($_GET['s']) ? $_GET['s'] : NULL),(isset($_GET['pg']) ? $_GET['pg'] : 0));
 					} else {
 						require_once('include/display.git_search.php');
-						git_search($gitphp_conf['projectroot'],$_GET['p'],(isset($_GET['h']) ? $_GET['h'] : NULL),(isset($_GET['s']) ? $_GET['s'] : NULL),(isset($_GET['st']) ? $_GET['st'] : "commit"),(isset($_GET['pg']) ? $_GET['pg'] : 0));
+						git_search($gitphp_conf['projectroot'],$project,(isset($_GET['h']) ? $_GET['h'] : NULL),(isset($_GET['s']) ? $_GET['s'] : NULL),(isset($_GET['st']) ? $_GET['st'] : "commit"),(isset($_GET['pg']) ? $_GET['pg'] : 0));
 					}
 					break;
 				case "tag":
 					require_once('include/display.git_tag.php');
-					git_tag($gitphp_conf['projectroot'],$_GET['p'],$_GET['h']);
+					git_tag($gitphp_conf['projectroot'],$project,$_GET['h']);
 					break;
 				default:
 					$tpl->assign("validaction", FALSE);
@@ -207,7 +226,7 @@
 	}
  } else {
 	require_once('include/display.git_project_list.php');
- 	git_project_list($gitphp_conf['projectroot'],$git_projects,(isset($_GET['o']) ? $_GET['o'] : "project"));
+	git_project_list($gitphp_conf['projectroot'], (isset($git_projects) ? $git_projects : null), (isset($_GET['o']) ? $_GET['o'] : "project"));
  }
 
  if ($gitphp_conf['debug'] && $extraoutput)

--- a/templates/blob.tpl
+++ b/templates/blob.tpl
@@ -66,7 +66,7 @@
      {foreach from=$lines item=line name=lines}
        <tr>
          <td class="num"><a id="l{$smarty.foreach.lines.iteration}" href="#l{$smarty.foreach.lines.iteration}" class="linenr">{$smarty.foreach.lines.iteration}</a></td>
-	 <td class="codeline">{$line|escape:'htmlall'}</td>
+	 <td class="codeline">{$line|escape:'html'}</td>
      {/foreach}
      </table>
    {/if}

--- a/templates/filediff.tpl
+++ b/templates/filediff.tpl
@@ -8,13 +8,13 @@
 <div class="pre">
 {foreach from=$diff item=diffline}
   {if substr($diffline,0,1)=="+"}
-    <span class="diffplus">{$diffline|escape:'htmlall'}</span>
+    <span class="diffplus">{$diffline|escape:'html'}</span>
   {elseif substr($diffline,0,1)=="-"}
-    <span class="diffminus">{$diffline|escape:'htmlall'}</span>
+    <span class="diffminus">{$diffline|escape:'html'}</span>
   {elseif substr($diffline,0,1)=="@"}
-    <span class="diffat">{$diffline|escape:'htmlall'}</span>
+    <span class="diffat">{$diffline|escape:'html'}</span>
   {else}
-    <span>{$diffline|escape:'htmlall'}</span>
+    <span>{$diffline|escape:'html'}</span>
   {/if}
 {/foreach}
 </div>

--- a/templates/project.tpl
+++ b/templates/project.tpl
@@ -19,6 +19,12 @@
    <tr><td>description</td><td>{$description}</td></tr>
    <tr><td>owner</td><td>{$owner}</td></tr>
    <tr><td>last change</td><td>{$lastchange}</td></tr>
+   {if $cloneurl}
+     <tr><td>clone url</td><td>{$cloneurl}</td></tr>
+   {/if}
+   {if $pushurl}
+     <tr><td>push url</td><td>{$pushurl}</td></tr>
+   {/if}
  </table>
  <div>
    <a class="title" href="{$SCRIPT_NAME}?p={$project}&a=shortlog">shortlog</a>

--- a/templates/projectlist.tpl
+++ b/templates/projectlist.tpl
@@ -58,7 +58,7 @@
             <td>
               <a href="{$SCRIPT_NAME}?p={$plist[proj].project}&a=summary" class="list {if $categ != "none"}indent{/if}">{$plist[proj].project}</a>
             </td>
-            <td>{$plist[proj].descr}</td>
+            <td><a href="{$SCRIPT_NAME}?p={$plist[proj].project}&a=summary" class="list">{$plist[proj].descr}</a></td>
             <td><i>{$plist[proj].owner}</i></td>
             <td>
               {if $plist[proj].age < 7200}   {* 60*60*2, or 2 hours *}
@@ -82,7 +82,7 @@
           <td>
             <a href="{$SCRIPT_NAME}?p={$projects[proj].project}&a=summary" class="list">{$projects[proj].project}</a>
           </td>
-          <td>{$projects[proj].descr}</td>
+          <td><a href="{$SCRIPT_NAME}?p={$projects[proj].project}&a=summary" class="list">{$projects[proj].descr}</a></td>
           <td><i>{$projects[proj].owner}</i></td>
           <td>
             {if $projects[proj].age < 7200}   {* 60*60*2, or 2 hours *}

--- a/templates/rss.tpl
+++ b/templates/rss.tpl
@@ -15,12 +15,12 @@
 
     {section name=rssitem loop=$commitlines}
       <item>
-        <title>{$commitlines[rssitem].cdmday} {$commitlines[rssitem].cdmonth} {$commitlines[rssitem].cdhour}:{$commitlines[rssitem].cdminute} - {$commitlines[rssitem].title|escape:'htmlall'}</title>
-        <author>{$commitlines[rssitem].author|escape:'htmlall'}</author>
+        <title>{$commitlines[rssitem].cdmday} {$commitlines[rssitem].cdmonth} {$commitlines[rssitem].cdhour}:{$commitlines[rssitem].cdminute} - {$commitlines[rssitem].title|escape:'html'}</title>
+        <author>{$commitlines[rssitem].author|escape:'html'}</author>
         <pubDate>{$commitlines[rssitem].cdrfc2822}</pubDate>
         <guid isPermaLink="true">{$self}?p={$project}&amp;a=commit&amp;h={$commitlines[rssitem].commit}</guid>
         <link>{$self}?p={$project}&amp;a=commit&amp;h={$commitlines[rssitem].commit}</link>
-        <description>{$commitlines[rssitem].title|escape:'htmlall'}</description>
+        <description>{$commitlines[rssitem].title|escape:'html'}</description>
         <content:encoded>
           <![CDATA[
           {foreach from=$commitlines[rssitem].comment item=line}

comments