1<?php 2// WebSVN - Subversion repository viewing via the web using PHP 3// Copyright (C) 2004-2006 Tim Armes 4// 5// This program is free software; you can redistribute it and/or modify 6// it under the terms of the GNU General Public License as published by 7// the Free Software Foundation; either version 2 of the License, or 8// (at your option) any later version. 9// 10// This program is distributed in the hope that it will be useful, 11// but WITHOUT ANY WARRANTY; without even the implied warranty of 12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13// GNU General Public License for more details. 14// 15// You should have received a copy of the GNU General Public License 16// along with this program; if not, write to the Free Software 17// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18// 19// -- 20// 21// authz.php 22// 23// Handle SVN access file 24 25class Authorization { 26 var $accessCache = array(); 27 var $accessFile = null; 28 var $user = null; 29 30 // {{{ __construct 31 32 function __construct() { 33 $this->setUsername(); 34 } 35 36 // }}} 37 38 function hasUsername() { 39 return $this->user !== null; 40 } 41 42 function addAccessFile($accessFile) { 43 $this->accessFile = $accessFile; 44 } 45 46 // {{{ setUsername() 47 // 48 // Set the username from the current http session 49 50 function setUsername() { 51 if (isset($_SERVER['REMOTE_USER'])) { 52 $this->user = $_SERVER['REMOTE_USER']; 53 } else if (isset($_SERVER['REDIRECT_REMOTE_USER'])) { 54 $this->user = $_SERVER['REDIRECT_REMOTE_USER']; 55 } else if (isset($_SERVER['PHP_AUTH_USER'])) { 56 $this->user = $_SERVER['PHP_AUTH_USER']; 57 } 58 } 59 60 // }}} 61 62 // Private function to simplify creation of common SVN authz command string text. 63 function svnAuthzCommandString($repo, $path, $checkSubDirs = false) { 64 global $config; 65 66 $cmd = $config->getSvnAuthzCommand(); 67 $repoAndPath = '--repository ' . quote($repo) . ' --path ' . quote($path); 68 $username = !$this->hasUsername() ? '' : '--username ' . quote($this->user); 69 $subDirs = !$checkSubDirs ? '' : '-R'; 70 $authzFile = quote($this->accessFile); 71 $retVal = "${cmd} ${repoAndPath} ${username} ${subDirs} ${authzFile}"; 72 73 return $retVal; 74 } 75 76 // {{{ hasReadAccess 77 // 78 // Returns true if the user has read access to the given path 79 80 function hasReadAccess($repos, $path, $checkSubDirs = false) { 81 if ($this->accessFile == null) 82 return false; 83 84 if ($path == '' || $path[0] != '/') { 85 $path = '/'.$path; 86 } 87 88 $cmd = $this->svnAuthzCommandString($repos, $path, $checkSubDirs); 89 $result = 'no'; 90 91 // Access checks might be issued multiple times for the same repos and paths within one and 92 // the same request, introducing a lot of overhead because of "svnauthz" especially with 93 // many repos under Windows. The easiest way to somewhat optimize it for different scenarios 94 // is using a cache. 95 // 96 // https://github.com/websvnphp/websvn/issues/78#issuecomment-489306169 97 $cache =& $this->accessCache; 98 $cached = isset($cache[$cmd]) ? $cache[$cmd] : null; 99 $cachedWhen = isset($cached) ? $cached['when'] : 0; 100 $cachedExpired = (time() - 60) > $cachedWhen; 101 102 if ($cachedExpired) { 103 // Sorting by "when" should be established somehow to only remove the oldest element 104 // instead of an arbitrary first one, which might be the newest added last time. 105 if (count($cache) >= 1000) { 106 array_shift($cache); 107 } 108 109 $result = runCommand($cmd)[0]; 110 $cache[$cmd] = array('when' => time(), 111 'result' => $result); 112 } else { 113 $result = $cached['result']; 114 } 115 116 return $result != 'no'; 117 } 118 119 // }}} 120 121 // {{{ hasUnrestrictedReadAccess 122 // 123 // Returns true if the user has read access to the given path and too 124 // all subdirectories 125 126 function hasUnrestrictedReadAccess($repos, $path) { 127 return $this->hasReadAccess($repos, $path, true); 128 } 129 130 // }}} 131 132} 133