Rev 185 Rev 4988
1 <?php 1 <?php
2 # vim:et:ts=3:sts=3:sw=3:fdm=marker: -  
3   -  
4 // WebSVN - Subversion repository viewing via the web using PHP 2 // WebSVN - Subversion repository viewing via the web using PHP
5 // Copyright © 2004-2006 Tim Armes, Matt Sicker 3 // Copyright (C) 2004-2006 Tim Armes
6 // 4 //
7 // This program is free software; you can redistribute it and/or modify 5 // 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 6 // 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 7 // the Free Software Foundation; either version 2 of the License, or
10 // (at your option) any later version. 8 // (at your option) any later version.
11 // 9 //
12 // This program is distributed in the hope that it will be useful, 10 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details. 13 // GNU General Public License for more details.
16 // 14 //
17 // You should have received a copy of the GNU General Public License 15 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software 16 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // 18 //
21 // -- 19 // --
22 // 20 //
23 // comp.php 21 // comp.php
24 // 22 //
25 // Compare two paths using "svn diff" 23 // Compare two paths using `svn diff`
26 // 24 //
27   25  
28 require_once("include/setup.inc"); 26 require_once 'include/setup.php';
29 require_once("include/svnlook.inc"); 27 require_once 'include/svnlook.php';
30 require_once("include/utils.inc"); 28 require_once 'include/utils.php';
31 require_once("include/template.inc"); 29 require_once 'include/template.php';
32   30  
33 $svnrep = new SVNRepository($rep); 31 function checkRevision($rev)
-   32 {
-   33 if (is_numeric($rev) && ((int)$rev > 0))
-   34 {
-   35 return $rev;
-   36 }
-   37 return 'HEAD';
-   38 }
34   39  
35 function checkRevision($rev) 40 // Make sure that we have a repository
-   41 if (!$rep)
36 { 42 {
37 if (is_numeric($rev) && ((int)$rev > 0)) -  
38 return $rev; -  
39 -  
40 $rev = strtoupper($rev); 43 renderTemplate404('compare','NOREP');
41 -  
42 switch($rev) -  
43 { -  
44 case "HEAD": -  
45 case "PREV": -  
46 case "COMMITTED": -  
47 return $rev; -  
48 } -  
49 -  
50 return "HEAD"; -  
51 } 44 }
52   45  
53 $svnrep = new SVNRepository($rep); 46 $svnrep = new SVNRepository($rep);
54   47  
55 // Retrieve the request information 48 // Retrieve the request information
56 $path1 = @$_REQUEST["compare"][0]; 49 $path1 = @$_REQUEST['compare'][0];
57 $path2 = @$_REQUEST["compare"][1]; 50 $path2 = @$_REQUEST['compare'][1];
58 $rev1 = @$_REQUEST["compare_rev"][0]; 51 $rev1 = (int)@$_REQUEST['compare_rev'][0];
59 $rev2 = @$_REQUEST["compare_rev"][1]; 52 $rev2 = (int)@$_REQUEST['compare_rev'][1];
-   53 $manualorder = (@$_REQUEST['manualorder'] == 1);
-   54 $ignoreWhitespace = $config->getIgnoreWhitespacesInDiff();
-   55  
-   56 if (array_key_exists('ignorews', $_REQUEST))
-   57 {
-   58 $ignoreWhitespace = (bool)$_REQUEST['ignorews'];
-   59 }
60   60  
61 // Some page links put the revision with the path... 61 // Some page links put the revision with the path...
-   62 if ($path1 && strpos($path1, '@'))
-   63 {
62 if (strpos($path1, "@")) list($path1, $rev1) = explode("@", $path1); 64 list($path1, $rev1) = explode('@', $path1);
-   65 }
-   66 else if ($path1 && (strpos($path1, '@') === 0))
-   67 {
-   68 // Something went wrong. The path is missing.
-   69 $rev1 = substr($path1, 1);
-   70 $path1 = '/';
-   71 }
-   72  
-   73 if ($path2 && strpos($path2, '@'))
-   74 {
63 if (strpos($path2, "@")) list($path2, $rev2) = explode("@", $path2); 75 list($path2, $rev2) = explode('@', $path2);
-   76 }
-   77 else if ($path2 && (strpos($path2, '@') === 0))
-   78 {
-   79 $rev2 = substr($path2, 1);
-   80 $path2 = '/';
-   81 }
64   82  
65 $rev1 = checkRevision($rev1); 83 $rev1 = checkRevision($rev1);
66 $rev2 = checkRevision($rev2); 84 $rev2 = checkRevision($rev2);
67   85  
68 // Choose a sensible comparison order unless told not to 86 // Choose a sensible comparison order unless told not to
-   87  
-   88 if (!$manualorder && is_numeric($rev1) && is_numeric($rev2) && $rev1 > $rev2)
-   89 {
-   90 $temppath = $path1;
-   91 $path1 = $path2;
-   92 $path2 = $temppath;
-   93  
-   94 $temprev = $rev1;
-   95 $rev1 = $rev2;
-   96 $rev2 = $temprev;
-   97 }
-   98  
-   99 $vars['rev1url'] = $config->getURL($rep, $path1, 'dir').createRevAndPegString($rev1, $rev1);
-   100 $vars['rev2url'] = $config->getURL($rep, $path2, 'dir').createRevAndPegString($rev2, $rev2);
-   101  
-   102 $url = $config->getURL($rep, '', 'comp');
-   103 $vars['reverselink'] = '<a href="'.$url.'compare%5B%5D='.rawurlencode($path2 ?? '').'@'.$rev2.'&amp;compare%5B%5D='.rawurlencode($path1 ?? '').'@'.$rev1.'&amp;manualorder=1'.($ignoreWhitespace ? '&amp;ignorews=1' : '').'">'.$lang['REVCOMP'].'</a>';
-   104 $toggleIgnoreWhitespace = '';
-   105  
-   106 if ($ignoreWhitespace == $config->getIgnoreWhitespacesInDiff())
-   107 {
-   108 $toggleIgnoreWhitespace = '&amp;ignorews='.($ignoreWhitespace ? '0' : '1');
-   109 }
-   110  
-   111 if (!$ignoreWhitespace)
-   112 {
69 if (!@$_REQUEST["manualorder"] && is_numeric($rev1) && is_numeric($rev2)) 113 $vars['ignorewhitespacelink'] = '<a href="'.$url.'compare%5B%5D='.rawurlencode($path1 ?? '').'@'.$rev1.'&amp;compare%5B%5D='.rawurlencode($path2 ?? '').'@'.$rev2.($manualorder ? '&amp;manualorder=1' : '').$toggleIgnoreWhitespace.'">'.$lang['IGNOREWHITESPACE'].'</a>';
-   114 }
-   115 else
-   116 {
-   117 $vars['regardwhitespacelink'] = '<a href="'.$url.'compare%5B%5D='.rawurlencode($path1 ?? '').'@'.$rev1.'&amp;compare%5B%5D='.rawurlencode($path2 ?? '').'@'.$rev2.($manualorder ? '&amp;manualorder=1' : '').$toggleIgnoreWhitespace.'">'.$lang['REGARDWHITESPACE'].'</a>';
-   118 }
-   119  
-   120 if ($rev1 == 0) $rev1 = 'HEAD';
-   121 if ($rev2 == 0) $rev2 = 'HEAD';
-   122  
-   123 $vars['repname'] = escape($rep->getDisplayName());
-   124 $vars['action'] = $lang['PATHCOMPARISON'];
-   125  
-   126 $hidden = '<input type="hidden" name="manualorder" value="1" />';
-   127  
-   128 if ($config->multiViews)
-   129 {
-   130 $hidden .= '<input type="hidden" name="op" value="comp"/>';
-   131 }
-   132 else
-   133 {
-   134 $hidden .= '<input type="hidden" name="repname" value="'.$repname.'" />';
-   135 }
-   136  
-   137 $vars['compare_form'] = '<form method="get" action="'.$url.'" id="compare">'.$hidden;
-   138 $vars['compare_path1input'] = '<input type="text" size="40" name="compare[0]" value="'.escape($path1).'" />';
-   139 $vars['compare_path2input'] = '<input type="text" size="40" name="compare[1]" value="'.escape($path2).'" />';
-   140 $vars['compare_rev1input'] = '<input type="text" size="5" name="compare_rev[0]" value="'.$rev1.'" />';
-   141 $vars['compare_rev2input'] = '<input type="text" size="5" name="compare_rev[1]" value="'.$rev2.'" />';
-   142 $vars['compare_submit'] = '<input name="comparesubmit" type="submit" value="'.$lang['COMPAREPATHS'].'" />';
-   143 $vars['compare_endform'] = '</form>';
-   144  
-   145 $vars['safepath1'] = escape($path1);
-   146 $vars['safepath2'] = escape($path2);
-   147  
-   148 $vars['rev1'] = $rev1;
-   149 $vars['rev2'] = $rev2;
-   150  
-   151 $history1 = $svnrep->getLog($path1, $rev1, 0, false, 1);
-   152 if (!$history1)
-   153 {
-   154 renderTemplate404('compare','NOPATH');
-   155 }
-   156 else
70 { 157 {
71 if ($rev1 > $rev2) -  
72 { -  
73 $temppath = $path1; -  
74 $temprev = $rev1; -  
75 -  
76 $path1 = $path2; -  
77 $rev1 = $rev2; -  
78 -  
79 $path2 = $temppath; -  
80 $rev2 = $temprev; -  
81 } -  
82 } -  
83   -  
84 $url = $config->getURL($rep, "/", "comp"); 158 $history2 = $svnrep->getLog($path2, $rev2, 0, false, 1);
85 $vars["revlink"] = "<a href=\"${url}compare%5B%5D=".urlencode($path2)."@$rev2&amp;compare%5B%5D=".urlencode($path1)."@$rev1&manualorder=1\">${lang["REVCOMP"]}</a>"; -  
86   -  
87 if ($rev1 == 0) $rev1 = "HEAD"; -  
88 if ($rev2 == 0) $rev2 = "HEAD"; -  
89   -  
90 $vars["repname"] = $rep->getDisplayName(); -  
91 $vars["action"] = $lang["PATHCOMPARISON"]; -  
92 $vars["compare_form"] = "<form action=\"$url\" method=\"post\" name=\"compareform\">"; -  
93 $vars["compare_path1input"] = "<input type=\"text\" size=\"40\" name=\"compare[0]\" value=\"$path1\" />"; -  
94 $vars["compare_rev1input"] = "<input type=\"text\" size=\"5\" name=\"compare_rev[0]\" value=\"$rev1\" />"; -  
95 $vars["compare_path2input"] = "<input type=\"text\" size=\"40\" name=\"compare[1]\" value=\"$path2\" />"; -  
96 $vars["compare_rev2input"] = "<input type=\"text\" size=\"5\" name=\"compare_rev[1]\" value=\"$rev2\" />"; -  
97 $vars["compare_submit"] = "<input name=\"comparesubmit\" type=\"submit\" value=\"${lang["COMPAREPATHS"]}\" />"; -  
98 $vars["compare_endform"] = "<input type=\"hidden\" name=\"op\" value=\"comp\" /><input type=\"hidden\" name=\"manualorder\" value=\"1\" /><input type=\"hidden\" name=\"sc\" value=\"$showchanged\" /></form>"; -  
99   -  
100 # safe paths are a hack for fixing XSS sploit -  
101 $vars["path1"] = $path1; -  
102 $vars['safepath1'] = htmlentities($path1); -  
103 $vars["path2"] = $path2; -  
104 $vars['safepath2'] = htmlentities($path2); -  
105   159  
-   160 if (!$history2)
-   161 {
-   162 renderTemplate404('compare','NOPATH');
-   163 }
-   164 }
-   165  
-   166 // Set variables used for the more recent of the two revisions
-   167 $history = ($rev1 >= $rev2 ? $history1 : $history2);
-   168 if ($history && $history->curEntry)
-   169 {
-   170 $logEntry = $history->curEntry;
106 $vars["rev1"] = $rev1; 171 $vars['rev'] = $logEntry->rev;
107 $vars["rev2"] = $rev2; 172 $vars['peg'] = $peg;
-   173 $vars['date'] = $logEntry->date;
-   174 $vars['age'] = datetimeFormatDuration(time() - strtotime($logEntry->date));
-   175 $vars['author'] = $logEntry->author;
-   176 $vars['log'] = xml_entities($logEntry->msg);
-   177 }
-   178 else
-   179 {
-   180 $vars['warning'] = 'Problem with comparison.';
-   181 }
108   182  
109 $noinput = empty($path1) || empty($path2); 183 $noinput = empty($path1) || empty($path2);
110 $listing = array(); -  
111   184  
112 // Generate the diff listing 185 // Generate the diff listing
-   186  
-   187 $relativePath1 = $path1;
-   188 $relativePath2 = $path2;
-   189  
113 $path1 = encodepath(str_replace(DIRECTORY_SEPARATOR, "/", $svnrep->repConfig->path.$path1)); 190 $svnpath1 = encodepath($svnrep->getSvnPath(str_replace(DIRECTORY_SEPARATOR, '/', $path1 ?? '')));
114 $path2 = encodepath(str_replace(DIRECTORY_SEPARATOR, "/", $svnrep->repConfig->path.$path2)); 191 $svnpath2 = encodepath($svnrep->getSvnPath(str_replace(DIRECTORY_SEPARATOR, '/', $path2 ?? '')));
115   192  
116 $debug = false; 193 $debug = false;
117   194  
118 if (!$noinput) 195 if (!$noinput)
119 { 196 {
120 $rawcmd = $config->svn." diff ".$rep->svnParams().quote($path1."@".$rev1)." ".quote($path2."@".$rev2); 197 $cmd = $config->getSvnCommand().$rep->svnCredentials().' diff '.($ignoreWhitespace ? '-x "-w --ignore-eol-style" ' : '').quote($svnpath1.'@'.$rev1).' '.quote($svnpath2.'@'.$rev2);
121 $cmd = quoteCommand($rawcmd, true); 198 }
122 if ($debug) echo "$cmd\n"; 199  
123 } 200 function clearVars()
124   201 {
125 function clearVars() 202 global $ignoreWhitespace, $listing, $index;
126 { 203  
127 global $listing, $index; 204 if ($ignoreWhitespace && $index > 1)
128 205 {
129 $listing[$index]["newpath"] = null; 206 $endBlock = false;
130 $listing[$index]["endpath"] = null; 207 $previous = $index - 1;
131 $listing[$index]["info"] = null; 208 if ($listing[$previous]['endpath']) $endBlock = 'newpath';
132 $listing[$index]["diffclass"] = null; 209 else if ($listing[$previous]['enddifflines']) $endBlock = 'difflines';
133 $listing[$index]["difflines"] = null; 210  
134 $listing[$index]["enddifflines"] = null; 211 if ($endBlock !== false)
135 $listing[$index]["properties"] = null; 212 {
136 } 213 // check if block ending at previous contains real diff data
137   214 $i = $previous;
138 $vars["success"] = false; 215 $containsOnlyEqualDiff = true;
139   216 $addedLines = array();
140 if (!$noinput) 217 $removedLines = array();
141 { 218 while ($i >= 0 && !$listing[$i - 1][$endBlock])
142 if ($diff = popen($cmd, "r")) 219 {
143 { 220 $diffclass = $listing[$i - 1]['diffclass'];
144 $index = 0; 221  
145 $indiff = false; 222 if ($diffclass !== 'diffadded' && $diffclass !== 'diffdeleted')
146 $indiffproper = false; 223 {
147 $getLine = true; 224 if ($addedLines !== $removedLines)
148 $node = null; 225 {
149 226 $containsOnlyEqualDiff = false;
150 $vars["success"] = true; 227 break;
151 228 }
152 while (!feof($diff)) 229 }
153 { 230  
154 if ($getLine) 231 if (count($addedLines) > 0 && $addedLines === $removedLines)
155 $line = fgets($diff); 232 {
156 233 $addedLines = array();
157 clearVars(); 234 $removedLines = array();
158 $getLine = true; 235 }
159 if ($debug) print "Line = '$line'<br />" ; 236  
160 if ($indiff) 237 if ($diffclass === 'diff')
161 { 238 {
162 // If we're in a diff proper, just set up the line 239 $i--;
163 if ($indiffproper) 240 continue;
164 { 241 }
165 if ($line[0] == " " || $line[0] == "+" || $line[0] == "-") 242  
166 { 243 if ($diffclass === null)
167 switch ($line[0]) 244 {
168 { 245 $containsOnlyEqualDiff = false;
169 case " ": 246 break;;
170 $listing[$index]["diffclass"] = "diff"; 247 }
171 $subline = hardspace(replaceEntities(rtrim(substr($line, 1)), $rep)); 248  
172 if (empty($subline)) $subline = "&nbsp;"; 249 if ($diffclass === 'diffdeleted')
173 $listing[$index++]["line"] = $subline; 250 {
174 if ($debug) print "Including as diff: $subline<br />"; 251 if (count($addedLines) <= count($removedLines))
175 break; 252 {
176 253 $containsOnlyEqualDiff = false;
177 case "+": 254 break;;
178 $listing[$index]["diffclass"] = "diffadded"; 255 }
179 $subline = hardspace(replaceEntities(rtrim(substr($line, 1)), $rep)); 256  
180 if (empty($subline)) $subline = "&nbsp;"; 257 array_unshift($removedLines, $listing[$i - 1]['line']);
181 $listing[$index++]["line"] = $subline; 258 $i--;
182 if ($debug) print "Including as added: $subline<br />"; 259 continue;
183 break; 260 }
184 261  
185 case "-": 262 if ($diffclass === 'diffadded')
186 $listing[$index]["diffclass"] = "diffdeleted"; 263 {
187 $subline = hardspace(replaceEntities(rtrim(substr($line, 1)), $rep)); 264 if (count($removedLines) > 0)
188 if (empty($subline)) $subline = "&nbsp;"; 265 {
189 $listing[$index++]["line"] = $subline; 266 $containsOnlyEqualDiff = false;
190 if ($debug) print "Including as removed: $subline<br />"; 267 break;;
191 break; 268 }
192 } 269  
193 270 array_unshift($addedLines, $listing[$i - 1]['line']);
194 continue; 271 $i--;
195 } 272 continue;
196 else 273 }
197 { 274  
198 $indiffproper = false; 275 assert(false);
199 $listing[$index++]["enddifflines"] = true; 276 }
200 $getLine = false; 277  
201 if ($debug) print "Ending lines<br />"; 278 if ($containsOnlyEqualDiff)
202 continue; 279 {
203 } 280 $containsOnlyEqualDiff = $addedLines === $removedLines;
204 } 281 }
205 282  
206 // Check for the start of a new diff area 283 // remove blocks which only contain diffclass=diff and equal removes and adds
207 if (!strncmp($line, "@@", 2)) 284 if ($containsOnlyEqualDiff)
208 { 285 {
209 $pos = strpos($line, "+"); 286 for ($j = $i - 1; $j < $index; $j++)
210 $posline = substr($line, $pos); 287 {
211 sscanf($posline, "+%d,%d", $sline, $eline); 288 unset($listing[$j]);
212 if ($debug) print "sline = '$sline', eline = '$eline'<br />"; 289 }
213 // Check that this isn't a file deletion 290  
214 if ($sline == 0 && $eline == 0) 291 $index = $i - 1;
215 { 292 }
216 $line = fgets($diff); 293 }
217 if ($debug) print "Ignoring: $line<br />" ; 294 }
218 while ($line[0] == " " || $line[0] == "+" || $line[0] == "-") 295  
219 { 296 $listvar = &$listing[$index];
220 $line = fgets($diff); 297 $listvar['newpath'] = null;
221 if ($debug) print "Ignoring: $line<br />" ; 298 $listvar['endpath'] = null;
222 } 299 $listvar['info'] = null;
223 300 $listvar['diffclass'] = null;
224 $getLine = false; 301 $listvar['difflines'] = null;
225 if ($debug) print "Unignoring previous - marking as deleted<b>"; 302 $listvar['enddifflines'] = null;
226 $listing[$index++]["info"] = $lang["FILEDELETED"]; 303 $listvar['properties'] = null;
227 } 304 }
228 else 305  
229 { 306 $vars['success'] = false;
230 $listing[$index++]["difflines"] = $line; 307  
231 $indiffproper = true; 308 if (!$noinput)
232 } 309 {
233 310 // TODO: Report warning/error if comparison encounters any problems
234 continue; 311 if ($diff = popenCommand($cmd, 'r'))
235 } 312 {
236 else 313 $listing = array();
237 { 314 $index = 0;
238 $indiff = false; 315 $indiff = false;
239 if ($debug) print "Ending diff"; 316 $indiffproper = false;
240 } 317 $getLine = true;
241 } 318 $node = null;
242 319 $bufferedLine = false;
243 // Check for a new node entry 320  
244 if (strncmp(trim($line), "Index: ", 7) == 0) 321 $vars['success'] = true;
245 { 322  
246 // End the current node 323 while (!feof($diff))
247 if ($node) 324 {
248 { 325 if ($getLine)
249 $listing[$index++]["endpath"] = true; 326 {
250 clearVars(); 327 if ($bufferedLine === false)
251 } 328 {
252 329 $bufferedLine = rtrim(fgets($diff), "\n\r");
253 $node = trim($line); 330 }
254 $node = substr($node, 7); 331  
255 332 $newlineR = strpos($bufferedLine, "\r");
256 $listing[$index]["newpath"] = $node; 333 $newlineN = strpos($bufferedLine, "\n");
257 if ($debug) echo "Creating node $node<br />"; 334 if ($newlineR === false && $newlineN === false)
258 335 {
259 // Skip past the line of ='s 336 $line = $bufferedLine;
260 $line = fgets($diff); 337 $bufferedLine = false;
261 if ($debug) print "Skipping: $line<br />" ; 338 }
262 339 else
263 // Check for a file addition 340 {
264 $line = fgets($diff); 341 $newline = ($newlineR < $newlineN ? $newlineR : $newlineN);
265 if ($debug) print "Examining: $line<br />" ; 342 $line = substr($bufferedLine, 0, $newline);
266 if (strpos($line, "(revision 0)")) 343 $bufferedLine = substr($bufferedLine, $newline + 1);
267 $listing[$index]["info"] = $lang["FILEADDED"]; 344 }
268 345 }
269 if (strncmp(trim($line), "Cannot display:", 15) == 0) 346  
270 { 347 clearVars();
271 $index++; 348 $getLine = true;
272 clearVars(); 349 if ($debug) print 'Line = "'.$line.'"<br />';
273 $listing[$index++]["info"] = $line; 350 if ($indiff)
274 continue; 351 {
275 } 352 // If we're in a diff proper, just set up the line
276 353 if ($indiffproper)
277 // Skip second file info 354 {
278 $line = fgets($diff); 355 if (strlen($line) > 0 && ($line[0] == ' ' || $line[0] == '+' || $line[0] == '-'))
279 if ($debug) print "Skipping: $line<br />" ; 356 {
280 357 $subline = escape(toOutputEncoding(substr($line, 1)));
281 $indiff = true; 358 $subline = rtrim($subline, "\n\r");
282 $index++; 359 $subline = ($subline) ? expandTabs($subline) : '&nbsp;';
283 360 $listvar = &$listing[$index];
284 continue; 361 $listvar['line'] = $subline;
285 } 362  
286 363 switch ($line[0])
287 if (strncmp(trim($line), "Property changes on: ", 21) == 0) 364 {
288 { 365 case ' ':
289 $propnode = trim($line); 366 $listvar['diffclass'] = 'diff';
290 $propnode = substr($propnode, 21); 367 if ($debug) print 'Including as diff: '.$subline.'<br />';
291 368 break;
292 if ($debug) print "Properties on $propnode (cur node $ $node)"; 369  
293 if ($propnode != $node) 370 case '+':
294 { 371 $listvar['diffclass'] = 'diffadded';
295 if ($node) 372 if ($debug) print 'Including as added: '.$subline.'<br />';
296 { 373 break;
297 $listing[$index++]["endpath"] = true; 374  
298 clearVars(); 375 case '-':
299 } 376 $listvar['diffclass'] = 'diffdeleted';
300 377 if ($debug) print 'Including as removed: '.$subline.'<br />';
301 $node = $propnode; 378 break;
302 379 }
303 $listing[$index++]["newpath"] = $node; 380 $index++;
304 clearVars(); 381 }
305 } 382 else if ($line != '\ No newline at end of file')
306 383 {
307 $listing[$index++]["properties"] = true; 384 $indiffproper = false;
308 clearVars(); 385 $listing[$index++]['enddifflines'] = true;
309 if ($debug) echo "Creating node $node<br />"; 386 $getLine = false;
310 387 if ($debug) print 'Ending lines<br />';
311 // Skip the row of underscores 388 }
312 $line = fgets($diff); 389 continue;
313 if ($debug) print "Skipping: $line<br />" ; 390 }
314 391  
315 while ($line = trim(fgets($diff))) 392 // Check for the start of a new diff area
316 { 393 if (!strncmp($line, '@@', 2))
317 $listing[$index++]["info"] = $line; 394 {
318 clearVars(); 395 $pos = strpos($line, '+');
319 } 396 $posline = substr($line, $pos);
320 397 $sline = 0;
321 continue; 398 $eline = 0;
322 } 399 sscanf($posline, '+%d,%d', $sline, $eline);
323 400  
324 // Check for error messages 401 if ($debug) print 'sline = "'.$sline.'", eline = "'.$eline.'"<br />';
325 if (strncmp(trim($line), "svn: ", 5) == 0) 402  
326 { 403 // Check that this isn't a file deletion
327 $listing[$index++]["info"] = urldecode($line); 404 if ($sline == 0 && $eline == 0)
328 $vars["success"] = false; 405 {
329 continue; 406 $line = fgets($diff);
330 } 407 if ($debug) print 'Ignoring: "'.$line.'"<br />';
331 408  
332 $listing[$index++]["info"] = $line; 409 while ($line && ($line[0] == ' ' || $line[0] == '+' || $line[0] == '-'))
333 410 {
334 } 411 $line = fgets($diff);
335 412 if ($debug) print 'Ignoring: "'.$line.'"<br />';
336 if ($node) 413 }
337 { 414  
338 clearVars(); 415 $getLine = false;
339 $listing[$index++]["endpath"] = true; 416 if ($debug) print 'Unignoring previous - marking as deleted<br />';
340 } 417 $listing[$index++]['info'] = $lang['FILEDELETED'];
341 418  
342 if ($debug) print_r($listing); 419 }
343 } 420 else
344 } 421 {
345   422 $listvar = &$listing[$index];
346 $vars["version"] = $version; 423 $listvar['difflines'] = $line;
347   424 $sline = 0;
348 if (!$rep->hasUnrestrictedReadAccess($path1) || !$rep->hasUnrestrictedReadAccess($path2, false)) 425 $slen = 0;
349 $vars["noaccess"] = true; 426 $eline = 0;
350   427 $elen = 0;
351 parseTemplate($rep->getTemplatePath()."header.tmpl", $vars, $listing); 428 sscanf($line, '@@ -%d,%d +%d,%d @@', $sline, $slen, $eline, $elen);
352 parseTemplate($rep->getTemplatePath()."compare.tmpl", $vars, $listing); 429 $listvar['rev1line'] = $sline;
353 parseTemplate($rep->getTemplatePath()."footer.tmpl", $vars, $listing); 430 $listvar['rev1len'] = $slen;
354 431 $listvar['rev2line'] = $eline;
355 ?> 432 $listvar['rev2len'] = $elen;
-   433  
-   434 $indiffproper = true;
-   435  
-   436 $index++;
-   437 }
-   438  
-   439 continue;
-   440  
-   441 }
-   442 else
-   443 {
-   444 $indiff = false;
-   445 if ($debug) print 'Ending diff';
-   446 }
-   447 }
-   448  
-   449 // Check for a new node entry
-   450 if (strncmp(trim($line), 'Index: ', 7) == 0)
-   451 {
-   452 // End the current node
-   453 if ($node)
-   454 {
-   455 $listing[$index++]['endpath'] = true;
-   456 clearVars();
-   457 }
-   458  
-   459 $node = trim(toOutputEncoding($line));
-   460 $node = substr($node, 7);
-   461 if ($node == '' || $node[0] != '/') $node = '/'.$node;
-   462  
-   463 if (substr($path2, -strlen($node)) === $node)
-   464 {
-   465 $absnode = $path2;
-   466 }
-   467 else
-   468 {
-   469 $absnode = $path2;
-   470 if (substr($absnode, -1) == '/') $absnode = substr($absnode, 0, -1);
-   471 $absnode .= $node;
-   472 }
-   473  
-   474 $listvar = &$listing[$index];
-   475 $listvar['newpath'] = escape($absnode);
-   476  
-   477 $listvar['fileurl'] = $config->getURL($rep, $absnode, 'file').'rev='.$rev2;
-   478  
-   479 if ($debug) echo 'Creating node '.$node.'<br />';
-   480  
-   481 // Skip past the line of ='s
-   482 $line = fgets($diff);
-   483 if ($debug) print 'Skipping: '.$line.'<br />';
-   484  
-   485 // Check for a file addition
-   486 $line = fgets($diff);
-   487 if ($debug) print 'Examining: '.$line.'<br />';
-   488 if (strpos($line, '(revision 0)'))
-   489 {
-   490 $listvar['info'] = $lang['FILEADDED'];
-   491 }
-   492  
-   493 if (strncmp(trim($line), 'Cannot display:', 15) == 0)
-   494 {
-   495 $index++;
-   496 clearVars();
-   497 $listing[$index++]['info'] = escape(toOutputEncoding(rtrim($line, "\n\r")));
-   498 continue;
-   499 }
-   500  
-   501 // Skip second file info
-   502 $line = fgets($diff);
-   503 if ($debug) print 'Skipping: '.$line.'<br />';
-   504  
-   505 $indiff = true;
-   506 $index++;
-   507  
-   508 continue;
-   509 }
-   510  
-   511 if (strncmp(trim($line), 'Property changes on: ', 21) == 0)
-   512 {
-   513 $propnode = trim($line);
-   514 $propnode = substr($propnode, 21);
-   515 if ($propnode == '' || $propnode[0] != '/') $propnode = '/'.$propnode;
-   516  
-   517 if ($debug) print 'Properties on '.$propnode.' (cur node $ '.$node.')';
-   518 if ($propnode != $node)
-   519 {
-   520 if ($node)
-   521 {
-   522 $listing[$index++]['endpath'] = true;
-   523 clearVars();
-   524 }
-   525  
-   526 $node = $propnode;
-   527  
-   528 $listing[$index++]['newpath'] = escape(toOutputEncoding($node));
-   529 clearVars();
-   530 }
-   531  
-   532 $listing[$index++]['properties'] = true;
-   533 clearVars();
-   534 if ($debug) echo 'Creating node '.$node.'<br />';
-   535  
-   536 // Skip the row of underscores
-   537 $line = fgets($diff);
-   538 if ($debug) print 'Skipping: '.$line.'<br />';
-   539  
-   540 while ($line = rtrim(fgets($diff), "\n\r"))
-   541 {
-   542 if (!strncmp(trim($line), 'Index: ', 7))
-   543 {
-   544 break;
-   545 }
-   546 if (!strncmp(trim($line), '##', 2) || $line == '\ No newline at end of file')
-   547 {
-   548 continue;
-   549 }
-   550 $listing[$index++]['info'] = escape(toOutputEncoding($line));
-   551 clearVars();
-   552 }
-   553 $getLine = false;
-   554  
-   555 continue;
-   556 }
-   557  
-   558 // Check for error messages
-   559 if (strncmp(trim($line), 'svn: ', 5) == 0)
-   560 {
-   561 $listing[$index++]['info'] = urldecode($line);
-   562 $vars['success'] = false;
-   563 continue;
-   564 }
-   565  
-   566 $listing[$index++]['info'] = escape(toOutputEncoding($line));
-   567
-   568 if (strlen($line) === 0)
-   569 {
-   570 if (!isset($vars['warning']))
-   571 {
-   572 $vars['warning'] = "No changes between revisions";
-   573 }
-   574 }
-   575
-   576 }
-   577  
-   578 if ($node)
-   579 {
-   580 clearVars();
-   581 $listing[$index++]['endpath'] = true;
-   582 }
-   583  
-   584 if ($debug) print_r($listing);
-   585  
-   586 if (!$rep->hasUnrestrictedReadAccess($relativePath1) || !$rep->hasUnrestrictedReadAccess($relativePath2, false))
-   587 {
-   588 // check every item for access and remove it if read access is not allowed
-   589 $restricted = array();
-   590 $inrestricted = false;
-   591 foreach ($listing as $i => $item)
-   592 {
-   593 if ($item['newpath'] !== null)
-   594 {
-   595 $newpath = $item['newpath'];
-   596 $inrestricted = !$rep->hasReadAccess($newpath, false);
-   597 }
-   598  
-   599 if ($inrestricted)
-   600 {
-   601 $restricted[] = $i;
-   602 }
-   603  
-   604 if ($item['endpath'] !== null)
-   605 {
-   606 $inrestricted = false;
-   607 }
-   608 }
-   609  
-   610 foreach ($restricted as $i)
-   611 {
-   612 unset($listing[$i]);
-   613 }
-   614  
-   615 if (count($restricted) && !count($listing))
-   616 {
-   617 $vars['error'] = $lang['NOACCESS'];
-   618 sendHeaderForbidden();
-   619 }
-   620 }
-   621  
-   622 pclose($diff);
-   623 }
-   624 }
-   625  
-   626 renderTemplate('compare');