<?php# vim:et:ts=3:sts=3:sw=3:fdm=marker:// WebSVN - Subversion repository viewing via the web using PHP// Copyright © 2004-2006 Tim Armes, Matt Sicker//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA//// --//// configclass.inc4//// General class for handling configuration optionsrequire_once("include/command.inc");require_once("include/auth.inc");require_once("include/version.inc");// Auxillary functions used to sort repositories by name/group// {{{ cmpReps($a, $b)function cmpReps($a, $b){// First, sort by group$g = strcasecmp($a->group, $b->group);if ($g)return $g;// Same group? Sort by namereturn strcasecmp($a->name, $b->name);}// }}}// {{{ cmpGroups($a, $b)function cmpGroups($a, $b){$g = strcasecmp($a->group, $b->group);if ($g)return $g;return 0;}// }}}// {{{ mergesort(&$array, [$cmp_function])function mergesort(&$array, $cmp_function = 'strcmp'){// Arrays of size < 2 require no actionif (count($array) < 2)return;// Split the array in half$halfway = count($array) / 2;$array1 = array_slice($array, 0, $halfway);$array2 = array_slice($array, $halfway);// Recurse to sort the two halvesmergesort($array1, $cmp_function);mergesort($array2, $cmp_function);// If all of $array1 is <= all of $array2, just append them.if (call_user_func($cmp_function, end($array1), $array2[0]) < 1){$array = array_merge($array1, $array2);return;}// Merge the two sorted arrays into a single sorted array$array = array();$ptr1 = $ptr2 = 0;while ($ptr1 < count($array1) && $ptr2 < count($array2)){if (call_user_func($cmp_function, $array1[$ptr1], $array2[$ptr2]) < 1){$array[] = $array1[$ptr1++];}else{$array[] = $array2[$ptr2++];}}// Merge the remainderwhile ($ptr1 < count($array1)) $array[] = $array1[$ptr1++];while ($ptr2 < count($array2)) $array[] = $array2[$ptr2++];return;}// }}}// A Repository configuration classClass Repository{// {{{ Propertiesvar $name;var $svnName;var $path;var $group;var $username;var $password;// Local configuration options must start off unsetvar $allowDownload;var $minDownloadLevel;var $allowedExceptions = array();var $disallowedExceptions = array();var $rss;var $spaces;var $ignoreSvnMimeTypes;var $ignoreWebSVNContentTypes;var $bugtraq;var $auth;var $contentEnc;var $templatePath;// }}}// {{{ __construct($name, $svnName, $path, [$group, [$username, [$password]]])function Repository($name, $svnName, $path, $group = NULL, $username = NULL, $password = NULL){$this->name = $name;$this->svnName = $svnName;$this->path = $path;$this->group = $group;$this->username = $username;$this->password = $password;}// }}}// {{{ getDisplayName()function getDisplayName(){if(!empty($this->group))return $this->group.".".$this->name;elsereturn $this->name;}// }}}// {{{ svnParamsfunction svnParams(){if (!empty($this->username))return " --username ".$this->username." --password ".$this->password." ";elsereturn " ";}// }}}// Local configuration accessors// {{{ RSS Feedfunction hideRSS(){$this->rss = false;}function showRSS(){$this->rss = true;}function getHideRSS(){global $config;if (isset($this->rss))return $this->rss;return $config->getHideRSS();}// }}}// {{{ Downloadfunction allowDownload(){$this->allowDownload = true;}function disallowDownload(){$this->allowDownload = false;}function getAllowDownload(){global $config;if (isset($this->allowDownload))return $this->allowDownload;return $config->getAllowDownload();}function setMinDownloadLevel($level){$this->minDownloadLevel = $level;}function getMinDownloadLevel(){global $config;if (isset($this->minDownloadLevel))return $this->minDownloadLevel;return $config->getMinDownloadLevel();}function addAllowedDownloadException($path){if ($path{strlen($path) - 1} != "/")$path .= "/";$this->allowedExceptions[] = $path;}function addDisallowedDownloadException($path){if ($path{strlen($path) - 1} != "/")$path .= "/";$this->disallowedExceptions[] = $path;}function isDownloadAllowed($path){global $config;// Check global download optionif (!$this->getAllowDownload())return false;// Check with access moduleif (!$this->hasUnrestrictedReadAccess($path))return false;$subs = explode("/", $path);$level = count($subs) - 2;if ($level >= $this->getMinDownloadLevel()){// Level OK, search for disallowed exceptionsif ($config->findException($path, $this->disallowedExceptions))return false;if ($config->findException($path, $config->disallowedExceptions))return false;return true;}else{// Level not OK, search for disallowed exceptionsif ($config->findException($path, $this->allowedExceptions))return true;if ($config->findException($path, $config->allowedExceptions))return true;return false;}}// }}}// {{{ Templatesfunction setTemplatePath($path){$lastchar = substr($path, -1, 1);if (!($lastchar == DIRECTORY_SEPARATOR ||$lastchar == '/' ||$lastchar == '\\'))$path .= DIRECTORY_SEPARATOR;$this->templatePath = $path;}function getTemplatePath(){global $config;if (!empty($this->templatePath))return $this->templatePath;elsereturn $config->getTemplatePath();}// }}}// {{{ Tab expansionfunction expandTabsBy($sp){$this->spaces = $sp;}function getExpandTabsBy(){global $config;if (isset($this->spaces))return $this->spaces;return $config->getExpandTabsBy();}// }}}// {{{ MIME-Type Handingfunction ignoreSvnMimeTypes(){$this->ignoreSvnMimeTypes = true;}function useSvnMimeTypes(){$this->ignoreSvnMimeTypes = false;}function getIgnoreSvnMimeTypes(){global $config;if (isset($this->ignoreSvnMimeTypes))return $this->ignoreSvnMimeTypes;return $config->getIgnoreSvnMimeTypes();}function ignoreWebSVNContentTypes(){$this->ignoreWebSVNContentTypes = true;}function useWebSVNContentTypes(){$this->ignoreWebSVNContentTypes = false;}function getIgnoreWebSVNContentTypes(){global $config;if (isset($this->ignoreWebSVNContentTypes))return $this->ignoreWebSVNContentTypes;return $config->getIgnoreWebSVNContentTypes();}// }}}// {{{ Issue Trackingfunction useBugtraqProperties(){$this->bugtraq = true;}function ignoreBugtraqProperties(){$this->bugtraq = false;}function getBugtraq(){global $config;if (isset($this->bugtraq))return $this->bugtraq;return $config->getBugtraq();}// }}}// {{{ Encodingsfunction setContentEncoding($contentEnc){$this->contentEnc = $contentEnc;}function getContentEncoding(){global $config;if (isset($this->contentEnc))return $this->contentEnc;return $config->getContentEncoding();}// }}}// {{{ Authenticationfunction useAuthenticationFile($file){if (is_readable($file))$this->auth =& new Authentication($file);elsedie('Unable to read authentication file "'.$file.'"');}function hasReadAccess($path, $checkSubFolders = false){global $config;$a = null;if (isset($this->auth))$a =& $this->auth;else$a =& $config->getAuth();if (!empty($a))return $a->hasReadAccess($this->svnName, $path, $checkSubFolders);// No auth file - free access...return true;}function hasUnrestrictedReadAccess($path){global $config;$a = null;if (isset($this->auth))$a =& $this->auth;else$a =& $config->getAuth();if (!empty($a))return $a->hasUnrestrictedReadAccess($this->svnName, $path);// No auth file - free access...return true;}// }}}}// The general configuration classClass Config{// {{{ Properties// Tool path locationsvar $svnlook = "svnlook";var $svn = "svn --non-interactive --config-dir /tmp";var $svn_noparams = "svn --config-dir /tmp";var $diff = "diff";var $enscript ="enscript";var $sed = "sed";var $gzip = "gzip";var $tar = "tar";// Other configuration itemsvar $treeView = true;var $flatIndex = true;var $openTree = false;var $serverIsWindows = false;var $cacheResults = false;var $multiViews = false;var $useEnscript = false;var $allowDownload = false;var $minDownloadLevel = 0;var $allowedExceptions = array();var $disallowedExceptions = array();var $rss = true;var $spaces = 8;var $bugtraq = false;var $auth = "";var $templatePath = "./templates/Standard/";var $phpCompatPath = './include/PHP/Compat.php';var $ignoreSvnMimeTypes = false;var $ignoreWebSVNContentTypes = false;var $subversionMajorVersion = "";var $subversionMinorVersion = "";// Default character encodingsvar $inputEnc = ""; // Encoding of output returned from command linevar $contentEnc = ""; // Encoding of repository contentvar $outputEnc = "UTF-8"; // Encoding of web page. Now forced to UTF-8var $quote = "'";var $_repositories;// }}}// {{{ __construct()function Config(){}// }}}// {{{ Repository configurationfunction addRepository($name, $url, $group = NULL, $username = NULL, $password = NULL){$url = str_replace(DIRECTORY_SEPARATOR, "/", $url);if ($url{strlen($url) - 1} == "/")$url = substr($url, 0, -1);$svnName = substr($url, strrpos($url, "/") + 1);$this->_repositories[] = new Repository($name, $svnName, $url, $group, $username, $password);}function getRepositories(){return $this->_repositories;}function &findRepository($name){foreach ($this->_repositories as $index => $rep){if (strcmp($rep->getDisplayName(), $name) == 0){$repref =& $this->_repositories[$index];return $repref;}}print "ERROR: Unable to find repository '$name'";exit;}// }}}// {{{ setServerIsWindows//// The server is running on Windowsfunction setServerIsWindows(){$this->serverIsWindows = true;// Try to set the input encoding intelligently$cp = 0;if ($cp = @shell_exec("CHCP")){$cp = trim(substr($cp, strpos($cp, ":") + 1));settype($cp, "integer");}// Use the most sensible default value if that failedif ($cp == 0) $cp = 850;// We assume, as a default, that the encoding of the repository contents is// in iso-8859-1, to be compatible with compilers and the like.$this->setInputEncoding("CP$cp", "iso-8859-1");// On Windows machines, use double quotes around command line parameters$this->quote = '"';}// }}}// {{{ Caching// setCachingOn//// Set result caching onfunction setCachingOn(){$this->cacheResults = true;}function isCachingOn(){return $this->cacheResults;}// }}}// {{{ MultiViews// useMultiViews//// Use MultiViews to access the repositoryfunction useMultiViews(){$this->multiViews = true;}function getUseMultiViews(){return $this->multiViews;}// }}}// {{{ Enscript// useEnscript//// Use Enscript to colourise listingsfunction useEnscript(){$this->useEnscript = true;}function getUseEnscript(){return $this->useEnscript;}// }}}// {{{ RSS// offerRSS//// Use Enscript to colourise listingsfunction hideRSS($myrep = 0){if (empty($myrep))$this->rss = false;else{$repo =& $this->findRepository($myrep);$repo->hideRSS();}}function getHideRSS(){return $this->rss;}// }}}// {{{ Downloads// allowDownload//// Allow download of tarballsfunction allowDownload($myrep = 0){if (empty($myrep))$this->allowDownload = true;else{$repo =& $this->findRepository($myrep);$repo->allowDownload();}}function disallowDownload($myrep = 0){if (empty($myrep))$this->allowDownload = false;else{$repo =& $this->findRepository($myrep);$repo->disallowDownload();}}function getAllowDownload(){return $this->allowDownload;}function setMinDownloadLevel($level, $myrep = 0){if (empty($myrep))$this->minDownloadLevel = $level;else{$repo =& $this->findRepository($myrep);$repo->setMinDownloadLevel($level);}}function getMinDownloadLevel(){return $this->minDownloadLevel;}function addAllowedDownloadException($path, $myrep = 0){if ($path{strlen($path) - 1} != "/")$path .= "/";if (empty($myrep))$this->allowedExceptions[] = $path;else{$repo =& $this->findRepository($myrep);$repo->addAllowedDownloadException($path);}}function addDisallowedDownloadException($path, $myrep = 0){if ($path{strlen($path) - 1} != "/")$path .= "/";if (empty($myrep))$this->disallowedExceptions[] = $path;else{$repo =& $this->findRepository($myrep);$repo->addDisallowedDownloadException($path);}}function findException($path, $exceptions){foreach ($exceptions As $key => $exc){if (strncmp($exc, $path, strlen($exc)) == 0)return true;}return false;}// }}}// {{{ getURL//// Get the URL to a path name based on the current configfunction getURL($rep, $path, $op){$base = $_SERVER["SCRIPT_NAME"];if ($this->multiViews){// Remove the .phpif (eregi(".php$", $base)){// Remove the .php$base = substr($base, 0, -4);}if ($path && $path{0} != "/") $path = "/".$path;$url = $base;if (is_object($rep)){$url .= "/".$rep->getDisplayName().str_replace('%2F', '/', urlencode($path));if ($op != "dir" && $op != "file")$url .= "?op=$op&";else$url .= "?";}return $url;}else{switch ($op){case "dir":$fname = "listing.php";break;case "file":$fname = "filedetails.php";break;case "log":$fname = "log.php";break;case "diff":$fname = "diff.php";break;case "blame":$fname = "blame.php";break;case "form":$fname = "form.php";break;case "rss":$fname = "rss.php";break;case "dl":$fname = "dl.php";break;case "comp":$fname = "comp.php";break;}if ($rep == -1)return $fname."?path=".urlencode($path)."&";elsereturn $fname."?repname=".urlencode($rep->getDisplayName())."&path=".urlencode($path)."&";}}// }}}// {{{ Paths and Commands// setPath//// Set the location of the given pathfunction setPath(&$var, $path, $name, $params = ""){$lastchar = substr($path, -1, 1);$isDir = ($lastchar == DIRECTORY_SEPARATOR ||$lastchar == "/" ||$lastchar == "\\");if (!$isDir){$path .= DIRECTORY_SEPARATOR;}// On a windows machine we need to put spaces around the entire command// to allow for spaces in the pathif ($this->serverIsWindows)$var = "\"$path$name\"";else$var = "$path$name";$var .= " ".$params;}// setSVNCommandPath//// Define the location of the svn and svnlook commandsfunction setSVNCommandPath($path){$this->setPath($this->svn, $path, "svn", "--non-interactive --config-dir /tmp");$this->setPath($this->svn_noparams, $path, "svn", " --config-dir /tmp");$this->setPath($this->svnlook, $path, "svnlook");}function getSvnCommand(){return $this->svn;}function getCleanSvnCommand(){return $this->svn_noparams;}function getSvnlookCommand(){return $this->svnlook;}// setDiffPath//// Define the location of the diff commandfunction setDiffPath($path){$this->setPath($this->diff, $path, "diff");}function getDiffCommand(){return $this->diff;}// setEnscriptPath//// Define the location of the enscript commandfunction setEnscriptPath($path){$this->setPath($this->enscript, $path, "enscript");}function getEnscriptCommand(){return $this->enscript;}// setSedPath//// Define the location of the sed commandfunction setSedPath($path){$this->setPath($this->sed, $path, "sed");}function getSedCommand(){return $this->sed;}// setTarPath//// Define the location of the tar commandfunction setTarPath($path){$this->setPath($this->tar, $path, "tar");}function getTarCommand(){return $this->tar;}// setGzipPath//// Define the location of the GZip commandfunction setGzipPath($path){$this->setPath($this->gzip, $path, "gzip");}function getGzipCommand(){return $this->gzip;}// Templatesfunction setTemplatePath($path, $myrep = 0){if (empty($myrep)){$lastchar = substr($path, -1, 1);if (!($lastchar == DIRECTORY_SEPARATOR ||$lastchar == '/' ||$lastchar == '\\'))$path .= DIRECTORY_SEPARATOR;$this->templatePath = $path;}else{$repo =& $this->findRepository($myrep);$repo->setTemplatePath($path);}}function getTemplatePath(){return $this->templatePath;}// PHP Compat file (from PEAR)function setPHPCompatPath($path){$this->setPath($this->phpCompatPath, $path, 'Compat.php');}function getPHPCompatFile(){return trim($this->phpCompatPath);}// }}}// {{{ parentPath//// Automatically set up the repositories based on a parent pathfunction parentPath($path, $group = NULL){if ($handle = @opendir($path)){// For each file...while (false !== ($file = readdir($handle))){// That's also a non hidden directoryif (is_dir($path.DIRECTORY_SEPARATOR.$file) && $file{0} != "."){// And that contains a db directory (in an attempt to not include// non svn repositories.if (is_dir($path.DIRECTORY_SEPARATOR.$file.DIRECTORY_SEPARATOR."db")){// We add the repository to the list$this->addRepository($file, "file:///".$path.DIRECTORY_SEPARATOR.$file, $group);}}}closedir($handle);}// Sort the repositories into alphabetical orderif (!empty($this->_repositories))usort($this->_repositories, "cmpReps");}// }}}// {{{ Encoding functionsfunction setInputEncoding($systemEnc){$this->inputEnc = $systemEnc;if (!isset($this->contentEnc))$this->contentEnc = $systemEnc;}function getInputEncoding(){return $this->inputEnc;}function setContentEncoding($contentEnc, $myrep = 0){if (empty($myrep))$this->contentEnc = $contentEnc;else{$repo =& $this->findRepository($myrep);$repo->setContentEncoding($contentEnc);}}function getContentEncoding(){return $this->contentEnc;}// }}}// {{{ Tab expansion functionsfunction expandTabsBy($sp, $myrep = 0){if (empty($myrep))$this->spaces = $sp;else{$repo =& $this->findRepository($myrep);$repo->expandTabsBy($sp);}}function getExpandTabsBy(){return $this->spaces;}// }}}// {{{ Misc settingsfunction ignoreSvnMimeTypes(){$this->ignoreSvnMimeTypes = true;}function getIgnoreSvnMimeTypes(){return $this->ignoreSvnMimeTypes;}function ignoreWebSVNContentTypes(){$this->ignoreWebSVNContentTypes = true;}function getIgnoreWebSVNContentTypes(){return $this->ignoreWebSVNContentTypes;}function useBugtraqProperties($myrep = 0){if (empty($myrep))$this->bugtraq = true;else{$repo =& $this->findRepository($myrep);$repo->useBugtraqProperties();}}function getBugtraq(){return $this->bugtraq;}function useAuthenticationFile($file, $myrep = 0){if (empty($myrep)){if (is_readable($file))$this->auth = new Authentication($file);else{echo "Unable to read authentication file '$file'";exit;}}else{$repo =& $this->findRepository($myrep);$repo->useAuthenticationFile($file);}}function &getAuth(){return $this->auth;}function useTreeView(){$this->treeView = true;}function getUseTreeView(){return $this->treeView;}function useFlatView(){$this->treeView = false;}function useTreeIndex($open){$this->flatIndex = false;$this->openTree = $open;}function getUseFlatIndex(){return $this->flatIndex;}function getOpenTree(){return $this->openTree;}// setSubversionMajorVersion//// Set subversion major versionfunction setSubversionMajorVersion($subversionMajorVersion){$this->subversionMajorVersion = $subversionMajorVersion;}function getSubversionMajorVersion(){return $this->subversionMajorVersion;}// setSubversionMinorVersion//// Set subversion minor versionfunction setSubversionMinorVersion($subversionMinorVersion){$this->subversionMinorVersion = $subversionMinorVersion;}function getSubversionMinorVersion(){return $this->subversionMinorVersion;}// }}}// {{{ Sort the repostories//// This function sorts the repositories by group name. The contents of the// group are left in there original order, which will either be sorted if the// group was added using the parentPath function, or defined for the order in// which the repositories were included in the user's config file.//// Note that as of PHP 4.0.6 the usort command no longer preserves the order// of items that are considered equal (in our case, part of the same group).// The mergesort function preserves this order.function sortByGroup(){if (!empty($this->_repositories))mergesort($this->_repositories, "cmpGroups");}// }}}}?>