Rev Author Line No. Line
185 miho 1 <?php
2 # vim:et:ts=3:sts=3:sw=3:fdm=marker:
3  
4 // WebSVN - Subversion repository viewing via the web using PHP
5 // Copyright © 2004-2006 Tim Armes, Matt Sicker
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 2 of the License, or
10 // (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 //
21 // --
22 //
23 // auth.inc
24 //
25 // Handle reading and interpretation of an SVN auth file
26  
27 require_once("include/accessfile.inc");
28  
29 define("UNDEFINED", 0);
30 define("ALLOW", 1);
31 define("DENY", 2);
32  
33 class Authentication
34 {
35 var $rights;
36 var $user;
37 var $usersGroups = array();
38  
39 // {{{ __construct
40  
41 function Authentication($accessfile)
42 {
43 $this->rights = new IniFile();
44 $this->rights->readIniFile($accessfile);
45 $this->setUsername("");
46 $this->identifyGroups();
47 }
48  
49 // }}}
50  
51 // {{{ setUsername($username)
52 //
53 // Set the username if it is given, or
54 // get the user of the current http session
55  
56 function setUsername($username)
57 {
58 if ($username == "") // Use the current user
59 {
60 $this->user = @$_SERVER["REMOTE_USER"];
61 }
62 else
63 {
64 $this->user = $username;
65 }
66 }
67  
68 // }}}
69  
70 // {{{ identifyGroups()
71 //
72 // Checks to see which groups the user belongs to
73  
74 function identifyGroups()
75 {
76 $this->usersGroups[] = "*";
77  
78 if (is_array($this->rights->getValues("groups")))
79 {
80 foreach ($this->rights->getValues("groups") as $group => $names)
81 {
82 if (in_array(strtolower($this->user), preg_split('/\s*,\s*/', $names)))
83 $this->usersGroups[] = "@" . $group;
84 }
85 }
86 }
87  
88 // }}}
89  
90 // {{{ inList
91 //
92 // Check if the user is in the given list and return their read status
93 // if they are (UNDEFINED, ALLOW or DENY)
94  
95 function inList($accessors, $user)
96 {
97 $output = UNDEFINED;
98 foreach($accessors As $key => $rights)
99 {
100 $keymatch = false;
101  
102 if (in_array($key, $this->usersGroups) || !strcmp($key, strtolower($user)))
103 $keymatch = true;
104  
105 if ($keymatch)
106 {
107 if (strpos($rights, "r") !== false)
108 return ALLOW;
109 else
110 $output = DENY;
111 }
112 }
113  
114 return $output;
115 }
116  
117 // }}}
118  
119 // {{{ hasReadAccess
120 //
121 // Returns true if the user has read access to the given path
122  
123 function hasReadAccess($repos, $path, $checkSubFolders = false)
124 {
125 $access = UNDEFINED;
126 if ($path{0} != "/")
127 $path = "/$path";
128  
129 // If were told to, we should check sub folders of the path to see if there's
130 // a read access below this level. This is used to display the folders needed
131 // to get to the folder to which read access is granted.
132  
133 if ($checkSubFolders)
134 {
135 $sections = $this->rights->getSections();
136  
137 foreach($sections As $section => $accessers)
138 {
139 $qualified = $repos.":".$path;
140 $len = strlen($qualified);
141  
142 if ($len < strlen($section) && strncmp($section, $qualified, strlen($qualified)) == 0)
143 {
144 $access = $this->inList($accessers, $this->user);
145 }
146  
147 if ($access != ALLOW)
148 {
149 $len = strlen($path);
150 if ($len < strlen($section) && strncmp($section, $path, strlen($path)) == 0)
151 {
152 $access = $this->inList($accessers, $this->user);
153 }
154 }
155  
156 if ($access == ALLOW)
157 break;
158 }
159 }
160  
161 // If we still don't have access, check each subpath of the path until we find an
162 // access level...
163  
164 if ($access != ALLOW)
165 {
166 $access = UNDEFINED;
167  
168 do
169 {
170 $accessers = $this->rights->getValues($repos.":".$path);
171 if (!empty($accessers))
172 $access = $this->inList($accessers, $this->user);
173  
174 if ($access == UNDEFINED)
175 {
176 $accessers = $this->rights->getValues($path);
177 if (!empty($accessers))
178 $access = $this->inList($accessers, $this->user);
179 }
180  
181 // If we've not got a match, remove the sub directory and start again
182 if ($access == UNDEFINED)
183 {
184 if ($path == "/") break;
185 $path = substr($path, 0, strrpos(substr($path, 0, -1), "/") + 1);
186 }
187  
188 } while ($access == UNDEFINED && $path != "");
189 }
190  
191 return $access == ALLOW;
192 }
193  
194 // }}}
195  
196 // {{{ hasUnrestrictedReadAccess
197 //
198 // Returns true if the user has read access to the given path and too
199 // all subfolders
200  
201 function hasUnrestrictedReadAccess($repos, $path)
202 {
203 // First make sure that we have full read access at this level
204  
205 if (!$this->hasReadAccess($repos, $path, false))
206 return false;
207  
208 // Now check to see if there is a sub folder that's protected
209  
210 $sections = $this->rights->getSections();
211  
212 foreach($sections As $section => $accessers)
213 {
214 $qualified = $repos.":".$path;
215 $len = strlen($qualified);
216 $access = UNDEFINED;
217  
218 if ($len < strlen($section) && strncmp($section, $qualified, strlen($qualified)) == 0)
219 {
220 $access = $this->inList($accessers, $this->user);
221 }
222  
223 if ($access != DENY)
224 {
225 $len = strlen($path);
226 if ($len < strlen($section) && strncmp($section, $path, strlen($qualified)) == 0)
227 {
228 $access = $this->inList($accessers, $this->user);
229 }
230 }
231  
232 if ($access == DENY)
233 return false;
234 }
235  
236 return true;
237 }
238  
239 // }}}
240  
241 }
242 ?>