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 // comp.php
24 //
25 // Compare two paths using "svn diff"
26 //
27  
28 require_once("include/setup.inc");
29 require_once("include/svnlook.inc");
30 require_once("include/utils.inc");
31 require_once("include/template.inc");
32  
33 $svnrep = new SVNRepository($rep);
34  
35 function checkRevision($rev)
36 {
37 if (is_numeric($rev) && ((int)$rev > 0))
38 return $rev;
39  
40 $rev = strtoupper($rev);
41  
42 switch($rev)
43 {
44 case "HEAD":
45 case "PREV":
46 case "COMMITTED":
47 return $rev;
48 }
49  
50 return "HEAD";
51 }
52  
53 $svnrep = new SVNRepository($rep);
54  
55 // Retrieve the request information
56 $path1 = @$_REQUEST["compare"][0];
57 $path2 = @$_REQUEST["compare"][1];
58 $rev1 = @$_REQUEST["compare_rev"][0];
59 $rev2 = @$_REQUEST["compare_rev"][1];
60  
61 // Some page links put the revision with the path...
62 if (strpos($path1, "@")) list($path1, $rev1) = explode("@", $path1);
63 if (strpos($path2, "@")) list($path2, $rev2) = explode("@", $path2);
64  
65 $rev1 = checkRevision($rev1);
66 $rev2 = checkRevision($rev2);
67  
68 // Choose a sensible comparison order unless told not to
69 if (!@$_REQUEST["manualorder"] && is_numeric($rev1) && is_numeric($rev2))
70 {
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");
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  
106 $vars["rev1"] = $rev1;
107 $vars["rev2"] = $rev2;
108  
109 $noinput = empty($path1) || empty($path2);
110 $listing = array();
111  
112 // Generate the diff listing
113 $path1 = encodepath(str_replace(DIRECTORY_SEPARATOR, "/", $svnrep->repConfig->path.$path1));
114 $path2 = encodepath(str_replace(DIRECTORY_SEPARATOR, "/", $svnrep->repConfig->path.$path2));
115  
116 $debug = false;
117  
118 if (!$noinput)
119 {
120 $rawcmd = $config->svn." diff ".$rep->svnParams().quote($path1."@".$rev1)." ".quote($path2."@".$rev2);
121 $cmd = quoteCommand($rawcmd, true);
122 if ($debug) echo "$cmd\n";
123 }
124  
125 function clearVars()
126 {
127 global $listing, $index;
128  
129 $listing[$index]["newpath"] = null;
130 $listing[$index]["endpath"] = null;
131 $listing[$index]["info"] = null;
132 $listing[$index]["diffclass"] = null;
133 $listing[$index]["difflines"] = null;
134 $listing[$index]["enddifflines"] = null;
135 $listing[$index]["properties"] = null;
136 }
137  
138 $vars["success"] = false;
139  
140 if (!$noinput)
141 {
142 if ($diff = popen($cmd, "r"))
143 {
144 $index = 0;
145 $indiff = false;
146 $indiffproper = false;
147 $getLine = true;
148 $node = null;
149  
150 $vars["success"] = true;
151  
152 while (!feof($diff))
153 {
154 if ($getLine)
155 $line = fgets($diff);
156  
157 clearVars();
158 $getLine = true;
159 if ($debug) print "Line = '$line'<br />" ;
160 if ($indiff)
161 {
162 // If we're in a diff proper, just set up the line
163 if ($indiffproper)
164 {
165 if ($line[0] == " " || $line[0] == "+" || $line[0] == "-")
166 {
167 switch ($line[0])
168 {
169 case " ":
170 $listing[$index]["diffclass"] = "diff";
171 $subline = hardspace(replaceEntities(rtrim(substr($line, 1)), $rep));
172 if (empty($subline)) $subline = "&nbsp;";
173 $listing[$index++]["line"] = $subline;
174 if ($debug) print "Including as diff: $subline<br />";
175 break;
176  
177 case "+":
178 $listing[$index]["diffclass"] = "diffadded";
179 $subline = hardspace(replaceEntities(rtrim(substr($line, 1)), $rep));
180 if (empty($subline)) $subline = "&nbsp;";
181 $listing[$index++]["line"] = $subline;
182 if ($debug) print "Including as added: $subline<br />";
183 break;
184  
185 case "-":
186 $listing[$index]["diffclass"] = "diffdeleted";
187 $subline = hardspace(replaceEntities(rtrim(substr($line, 1)), $rep));
188 if (empty($subline)) $subline = "&nbsp;";
189 $listing[$index++]["line"] = $subline;
190 if ($debug) print "Including as removed: $subline<br />";
191 break;
192 }
193  
194 continue;
195 }
196 else
197 {
198 $indiffproper = false;
199 $listing[$index++]["enddifflines"] = true;
200 $getLine = false;
201 if ($debug) print "Ending lines<br />";
202 continue;
203 }
204 }
205  
206 // Check for the start of a new diff area
207 if (!strncmp($line, "@@", 2))
208 {
209 $pos = strpos($line, "+");
210 $posline = substr($line, $pos);
211 sscanf($posline, "+%d,%d", $sline, $eline);
212 if ($debug) print "sline = '$sline', eline = '$eline'<br />";
213 // Check that this isn't a file deletion
214 if ($sline == 0 && $eline == 0)
215 {
216 $line = fgets($diff);
217 if ($debug) print "Ignoring: $line<br />" ;
218 while ($line[0] == " " || $line[0] == "+" || $line[0] == "-")
219 {
220 $line = fgets($diff);
221 if ($debug) print "Ignoring: $line<br />" ;
222 }
223  
224 $getLine = false;
225 if ($debug) print "Unignoring previous - marking as deleted<b>";
226 $listing[$index++]["info"] = $lang["FILEDELETED"];
227 }
228 else
229 {
230 $listing[$index++]["difflines"] = $line;
231 $indiffproper = true;
232 }
233  
234 continue;
235 }
236 else
237 {
238 $indiff = false;
239 if ($debug) print "Ending diff";
240 }
241 }
242  
243 // Check for a new node entry
244 if (strncmp(trim($line), "Index: ", 7) == 0)
245 {
246 // End the current node
247 if ($node)
248 {
249 $listing[$index++]["endpath"] = true;
250 clearVars();
251 }
252  
253 $node = trim($line);
254 $node = substr($node, 7);
255  
256 $listing[$index]["newpath"] = $node;
257 if ($debug) echo "Creating node $node<br />";
258  
259 // Skip past the line of ='s
260 $line = fgets($diff);
261 if ($debug) print "Skipping: $line<br />" ;
262  
263 // Check for a file addition
264 $line = fgets($diff);
265 if ($debug) print "Examining: $line<br />" ;
266 if (strpos($line, "(revision 0)"))
267 $listing[$index]["info"] = $lang["FILEADDED"];
268  
269 if (strncmp(trim($line), "Cannot display:", 15) == 0)
270 {
271 $index++;
272 clearVars();
273 $listing[$index++]["info"] = $line;
274 continue;
275 }
276  
277 // Skip second file info
278 $line = fgets($diff);
279 if ($debug) print "Skipping: $line<br />" ;
280  
281 $indiff = true;
282 $index++;
283  
284 continue;
285 }
286  
287 if (strncmp(trim($line), "Property changes on: ", 21) == 0)
288 {
289 $propnode = trim($line);
290 $propnode = substr($propnode, 21);
291  
292 if ($debug) print "Properties on $propnode (cur node $ $node)";
293 if ($propnode != $node)
294 {
295 if ($node)
296 {
297 $listing[$index++]["endpath"] = true;
298 clearVars();
299 }
300  
301 $node = $propnode;
302  
303 $listing[$index++]["newpath"] = $node;
304 clearVars();
305 }
306  
307 $listing[$index++]["properties"] = true;
308 clearVars();
309 if ($debug) echo "Creating node $node<br />";
310  
311 // Skip the row of underscores
312 $line = fgets($diff);
313 if ($debug) print "Skipping: $line<br />" ;
314  
315 while ($line = trim(fgets($diff)))
316 {
317 $listing[$index++]["info"] = $line;
318 clearVars();
319 }
320  
321 continue;
322 }
323  
324 // Check for error messages
325 if (strncmp(trim($line), "svn: ", 5) == 0)
326 {
327 $listing[$index++]["info"] = urldecode($line);
328 $vars["success"] = false;
329 continue;
330 }
331  
332 $listing[$index++]["info"] = $line;
333  
334 }
335  
336 if ($node)
337 {
338 clearVars();
339 $listing[$index++]["endpath"] = true;
340 }
341  
342 if ($debug) print_r($listing);
343 }
344 }
345  
346 $vars["version"] = $version;
347  
348 if (!$rep->hasUnrestrictedReadAccess($path1) || !$rep->hasUnrestrictedReadAccess($path2, false))
349 $vars["noaccess"] = true;
350  
351 parseTemplate($rep->getTemplatePath()."header.tmpl", $vars, $listing);
352 parseTemplate($rep->getTemplatePath()."compare.tmpl", $vars, $listing);
353 parseTemplate($rep->getTemplatePath()."footer.tmpl", $vars, $listing);
354  
355 ?>