<?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
//
// --
//
// auth.inc
//
// Handle reading and interpretation of an SVN auth file
require_once("include/accessfile.inc");
define("UNDEFINED", 0);
define("ALLOW", 1);
define("DENY", 2);
class Authentication
{
var $rights;
var $user;
var $usersGroups = array();
// {{{ __construct
function Authentication($accessfile)
{
$this->rights = new IniFile();
$this->rights->readIniFile($accessfile);
$this->setUsername("");
$this->identifyGroups();
}
// }}}
// {{{ setUsername($username)
//
// Set the username if it is given, or
// get the user of the current http session
function setUsername($username)
{
if ($username == "") // Use the current user
{
$this->user = @$_SERVER["REMOTE_USER"];
}
else
{
$this->user = $username;
}
}
// }}}
// {{{ identifyGroups()
//
// Checks to see which groups the user belongs to
function identifyGroups()
{
$this->usersGroups[] = "*";
if (is_array($this->rights->getValues("groups")))
{
foreach ($this->rights->getValues("groups") as $group => $names)
{
if (in_array(strtolower($this->user), preg_split('/\s*,\s*/', $names)))
$this->usersGroups[] = "@" . $group;
}
}
}
// }}}
// {{{ inList
//
// Check if the user is in the given list and return their read status
// if they are (UNDEFINED, ALLOW or DENY)
function inList($accessors, $user)
{
$output = UNDEFINED;
foreach($accessors As $key => $rights)
{
$keymatch = false;
if (in_array($key, $this->usersGroups) || !strcmp($key, strtolower($user)))
$keymatch = true;
if ($keymatch)
{
if (strpos($rights, "r") !== false)
return ALLOW;
else
$output = DENY;
}
}
return $output;
}
// }}}
// {{{ hasReadAccess
//
// Returns true if the user has read access to the given path
function hasReadAccess($repos, $path, $checkSubFolders = false)
{
$access = UNDEFINED;
if ($path{0} != "/")
$path = "/$path";
// If were told to, we should check sub folders of the path to see if there's
// a read access below this level. This is used to display the folders needed
// to get to the folder to which read access is granted.
if ($checkSubFolders)
{
$sections = $this->rights->getSections();
foreach($sections As $section => $accessers)
{
$qualified = $repos.":".$path;
$len = strlen($qualified);
if ($len < strlen($section) && strncmp($section, $qualified, strlen($qualified)) == 0)
{
$access = $this->inList($accessers, $this->user);
}
if ($access != ALLOW)
{
$len = strlen($path);
if ($len < strlen($section) && strncmp($section, $path, strlen($path)) == 0)
{
$access = $this->inList($accessers, $this->user);
}
}
if ($access == ALLOW)
break;
}
}
// If we still don't have access, check each subpath of the path until we find an
// access level...
if ($access != ALLOW)
{
$access = UNDEFINED;
do
{
$accessers = $this->rights->getValues($repos.":".$path);
if (!empty($accessers))
$access = $this->inList($accessers, $this->user);
if ($access == UNDEFINED)
{
$accessers = $this->rights->getValues($path);
if (!empty($accessers))
$access = $this->inList($accessers, $this->user);
}
// If we've not got a match, remove the sub directory and start again
if ($access == UNDEFINED)
{
if ($path == "/") break;
$path = substr($path, 0, strrpos(substr($path, 0, -1), "/") + 1);
}
} while ($access == UNDEFINED && $path != "");
}
return $access == ALLOW;
}
// }}}
// {{{ hasUnrestrictedReadAccess
//
// Returns true if the user has read access to the given path and too
// all subfolders
function hasUnrestrictedReadAccess($repos, $path)
{
// First make sure that we have full read access at this level
if (!$this->hasReadAccess($repos, $path, false))
return false;
// Now check to see if there is a sub folder that's protected
$sections = $this->rights->getSections();
foreach($sections As $section => $accessers)
{
$qualified = $repos.":".$path;
$len = strlen($qualified);
$access = UNDEFINED;
if ($len < strlen($section) && strncmp($section, $qualified, strlen($qualified)) == 0)
{
$access = $this->inList($accessers, $this->user);
}
if ($access != DENY)
{
$len = strlen($path);
if ($len < strlen($section) && strncmp($section, $path, strlen($qualified)) == 0)
{
$access = $this->inList($accessers, $this->user);
}
}
if ($access == DENY)
return false;
}
return true;
}
// }}}
}
?>