4988 |
kaklik |
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 |
|
|
|
25 |
class 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 |
} |