1<%-- 2CDDL HEADER START 3 4The contents of this file are subject to the terms of the 5Common Development and Distribution License (the "License"). 6You may not use this file except in compliance with the License. 7 8See LICENSE.txt included in this distribution for the specific 9language governing permissions and limitations under the License. 10 11When distributing Covered Code, include this CDDL HEADER in each 12file and include the License file at LICENSE.txt. 13If applicable, add the following below this CDDL HEADER, with the 14fields enclosed by brackets "[]" replaced with your own identifying 15information: Portions Copyright [yyyy] [name of copyright owner] 16 17CDDL HEADER END 18 19Copyright (c) 2006, 2021, Oracle and/or its affiliates. All rights reserved. 20Portions Copyright 2011 Jens Elkner. 21Portions Copyright (c) 2020, Chris Fraire <cfraire@me.com>. 22--%> 23<%@page errorPage="error.jsp" import=" 24java.io.ByteArrayInputStream, 25java.io.OutputStream, 26java.io.InputStream, 27java.nio.charset.StandardCharsets, 28 29org.suigeneris.jrcs.diff.delta.Chunk, 30org.suigeneris.jrcs.diff.delta.Delta, 31org.opengrok.indexer.analysis.AbstractAnalyzer, 32org.opengrok.web.DiffData, 33org.opengrok.web.DiffType" 34%> 35<%! 36private String getAnnotateRevision(DiffData data) { 37 if (data.getType() == DiffType.OLD || data.getType() == DiffType.NEW) { 38 String rev = data.getRev(data.getType() == DiffType.NEW ? 1 : 0); 39 return "<script type=\"text/javascript\">/* <![CDATA[ */ " 40 + "document.rev = function() { return " + Util.htmlize(Util.jsStringLiteral(rev)) 41 + "; } /* ]]> */</script>"; 42 } 43 return ""; 44} 45%> 46<% 47{ 48 PageConfig cfg = PageConfig.get(request); 49 cfg.addScript("diff"); 50 cfg.checkSourceRootExistence(); 51 /** 52 * This block must be the first block before any other output in the 53 * response. 54 * 55 * If there is already any output written into the response, and we 56 * use the same response and reset the content and the headers then we have 57 * a collision with the response streams and the "getOutputStream() has 58 * already been called" exception occurs. 59 */ 60 DiffData data = cfg.getDiffData(); 61 request.setAttribute("diff.jsp-data", data); 62 if (data.getType() == DiffType.TEXT 63 && request.getParameter("action") != null 64 && request.getParameter("action").equals("download")) { 65 try (OutputStream o = response.getOutputStream()) { 66 for (int i = 0; i < data.getRevision().size(); i++) { 67 Delta d = data.getRevision().getDelta(i); 68 try (InputStream in = new ByteArrayInputStream(d.toString().getBytes(StandardCharsets.UTF_8))) { 69 response.setHeader("content-disposition", "attachment; filename=" 70 + cfg.getResourceFile().getName() + "@" + data.getRev(0) 71 + "-" + data.getRev(1) + ".diff"); 72 byte[] buffer = new byte[8192]; 73 int nr; 74 while ((nr = in.read(buffer)) > 0) { 75 o.write(buffer, 0, nr); 76 } 77 } 78 } 79 o.flush(); 80 o.close(); 81 return; 82 } 83 } 84} 85%><%@ 86 87include file="mast.jsp" 88 89%><% 90/* ---------------------- diff.jsp start --------------------- */ 91{ 92 PageConfig cfg = PageConfig.get(request); 93 DiffData data = (DiffData) request.getAttribute("diff.jsp-data"); 94 95 // the data is never null as the getDiffData always return valid object 96 if (data.getErrorMsg() != null) { 97 98%> 99<div class="src"> 100 <h3 class="error">Error:</h3> 101 <p><%= data.getErrorMsg() %></p> 102</div><% 103 } else if (data.getGenre() == AbstractAnalyzer.Genre.IMAGE) { 104 105 String link = request.getContextPath() + Prefix.DOWNLOAD_P 106 + Util.htmlize(cfg.getPath()); 107%> 108<div id="difftable"> 109 <table class="image" aria-label="table with old and new image"> 110 <thead> 111 <tr><th><%= data.getFilename() %> (revision <%= data.getRev(0) %>)</th> 112 <th><%= data.getFilename() %> (revision <%= data.getRev(1) %>)</th> 113 </tr> 114 </thead> 115 <tbody> 116 <tr><td><img src="<%= link %>?<%= QueryParameters.REVISION_PARAM_EQ %><%= data.getRev(0) %>" alt="previous image"/> 117 </td> 118 <td><img src="<%= link %>?<%= QueryParameters.REVISION_PARAM_EQ %><%= data.getRev(1) %>" alt="new image"/> 119 </td> 120 </tr> 121 </tbody> 122 </table> 123</div><% 124 125 } else if (data.getGenre() != AbstractAnalyzer.Genre.PLAIN && data.getGenre() != AbstractAnalyzer.Genre.HTML) { 126 127 String link = request.getContextPath() + Prefix.DOWNLOAD_P 128 + Util.htmlize(cfg.getPath()); 129%> 130<div id="src">Diffs for binary files cannot be displayed! Files are <a 131 href="<%= link %>?<%= QueryParameters.REVISION_PARAM_EQ %><%= data.getRev(0) %>"><%= 132 data.getFilename() %>(revision <%= data.getRev(0) %>)</a> and <a 133 href="<%= link %>?<%= QueryParameters.REVISION_PARAM_EQ %><%= data.getRev(1) %>"><%= 134 data.getFilename() %>(revision <%= data.getRev(1) %>)</a>. 135</div><% 136 137 } else if (data.getRevision().size() == 0) { 138 %> 139 <%= getAnnotateRevision(data) %> 140 <strong>No differences found!</strong><% 141 142 } else { 143 //-------- Do THE DIFFS ------------ 144 int ln1 = 0; 145 int ln2 = 0; 146 String rp1 = data.getParam(0); 147 String rp2 = data.getParam(1); 148 String reqURI = request.getRequestURI(); 149 String[] file1 = data.getFile(0); 150 String[] file2 = data.getFile(1); 151 152 DiffType type = data.getType(); 153 boolean full = data.isFull(); 154%> 155<%= getAnnotateRevision(data) %> 156<div id="diffbar"> 157 <div class="legend"> 158 <span class="d">Deleted</span> 159 <span class="a">Added</span> 160 </div> 161 <div class="tabs"><% 162 for (DiffType t : DiffType.values()) { 163 if (type == t) { 164 %> <span class="active"><%= t.toString() %><% 165 if (t == DiffType.OLD) { 166 %> ( <%= data.getRev(0) %> )<% 167 } else if (t == DiffType.NEW) { 168 %> ( <%= data.getRev(1) %> )<% 169 } 170 %></span><% 171 } else { 172 %> <span><a href="<%= reqURI %>?<%= QueryParameters.REVISION_1_PARAM_EQ %><%= rp1 %>& 173<%= QueryParameters.REVISION_2_PARAM_EQ %><%= rp2 %>& 174<%= QueryParameters.FORMAT_PARAM_EQ %><%= t.getAbbrev() %>& 175<%= QueryParameters.DIFF_LEVEL_PARAM_EQ %><%= full ? '1' : '0'%>"><%= t.toString() %> 176 <% 177 if (t == DiffType.OLD) { 178 %> ( <%= data.getRev(0) %> )<% 179 } else if (t == DiffType.NEW) { 180 %> ( <%= data.getRev(1) %> )<% 181 } 182 %></a></span><% 183 } 184 } 185 %></div> 186 <div class="ctype"><% 187 if (!full) { 188 %> 189 <span><a href="<%= reqURI %>?<%= QueryParameters.REVISION_1_PARAM_EQ %><%= rp1 %>& 190<%= QueryParameters.REVISION_2_PARAM_EQ %><%= rp2 %>& 191<%= QueryParameters.FORMAT_PARAM_EQ %><%= type.getAbbrev() %>& 192<%= QueryParameters.DIFF_LEVEL_PARAM_EQ %>1">full</a></span> 193 <span class="active">compact</span><% 194 } else { 195 %> 196 <span class="active">full</span> 197 <span> <a href="<%= reqURI %>?<%= QueryParameters.REVISION_1_PARAM_EQ %><%= rp1 %>& 198<%= QueryParameters.REVISION_2_PARAM_EQ %><%= rp2 %>& 199<%= QueryParameters.FORMAT_PARAM_EQ %><%= type.getAbbrev() %>& 200<%= QueryParameters.DIFF_LEVEL_PARAM_EQ %>0">compact</a></span><% 201 } 202 %><span><a href="#" id="toggle-jumper">jumper</a></span> 203 <span><a href="<%= reqURI %>?<%= QueryParameters.REVISION_1_PARAM_EQ %><%= rp1 %>& 204<%= QueryParameters.REVISION_2_PARAM_EQ %><%= rp2 %>& 205<%= QueryParameters.FORMAT_PARAM_EQ %><%= DiffType.TEXT %>& 206action=download">download diff</a></span><% 207 %></div> 208</div> 209 210<div id="difftable"> 211 <div class="pre"><% 212 if (type == DiffType.SIDEBYSIDE || type == DiffType.UNIFIED) { 213 %><table class="plain" aria-label="table with old and new content"><% 214 if (type == DiffType.SIDEBYSIDE) { 215 %> 216 <thead><tr> 217 <th><%= data.getFilename() %> (<%= data.getRev(0) %>)</th> 218 <th><%= data.getFilename() %> (<%= data.getRev(1) %>)</th> 219 </tr></thead><% 220 } 221 %> 222 <tbody><% 223 } 224 225 for (int i=0; i < data.getRevision().size(); i++) { 226 Delta d = data.getRevision().getDelta(i); 227 if (type == DiffType.TEXT) { 228 %><%= Util.htmlize(d.toString()) %><% 229 } else { 230 Chunk c1 = d.getOriginal(); 231 Chunk c2 = d.getRevised(); 232 int cn1 = c1.first(); 233 int cl1 = c1.last(); 234 int cn2 = c2.first(); 235 int cl2 = c2.last(); 236 237 int i1 = cn1, i2 = cn2; 238 StringBuilder bl1 = new StringBuilder(80); 239 StringBuilder bl2 = new StringBuilder(80); 240 for (; i1 <= cl1 && i2 <= cl2; i1++, i2++) { 241 String[] ss = Util.diffline( 242 new StringBuilder(file1[i1]), 243 new StringBuilder(file2[i2])); 244 file1[i1] = ss[0]; 245 file2[i2] = ss[1]; 246 } 247 // deleted 248 for (; i1 <= cl1; i1++) { 249 bl1.setLength(0); 250 bl1.append("<span class=\"d\">"); 251 Util.htmlize(file1[i1], bl1); 252 file1[i1] = bl1.append("</span>").toString(); 253 } 254 // added 255 for (; i2 <= cl2; i2++) { 256 bl2.setLength(0); 257 bl2.append("<span class=\"a\">"); 258 Util.htmlize(file2[i2], bl2); 259 file2[i2] = bl2.append("</span>").toString(); 260 } 261 262 if (type == DiffType.UNIFIED) { 263// UDIFF 264 if (cn1 > ln1 || cn2 > ln2) { 265 %> 266 <tr class="k"><td><% 267 if (full || (cn2 - ln2 < 20)) { 268 for (int j = ln2; j < cn2; j++) { 269 %><span class="it"><%= ++ln2 %></span><%= 270 Util.htmlize(file2[j]) %><br/><% 271 } 272 } else { 273 for (int j = ln2; j < ln2 + 8; j++) { 274 %><span class="it"><%= j+1 %></span><%= 275 Util.htmlize(file2[j]) %><br/><% 276 } 277 %><br/>--- <strong><%= cn2 - ln2 - 16 278 %> unchanged lines hidden</strong> (<a href="<%= reqURI 279%>?<%= QueryParameters.REVISION_1_PARAM_EQ %><%= rp1 %>& 280<%= QueryParameters.REVISION_2_PARAM_EQ %><%= rp2 %>& 281<%= QueryParameters.FORMAT_PARAM_EQ %><%= type.getAbbrev() %>& 282<%= QueryParameters.DIFF_LEVEL_PARAM_EQ %>1#<%= ln2 %>">view full</a>) 283 --- <br/><br/><% 284 ln2 = cn2 - 8; 285 for (int j = ln2; j < cn2; j++) { 286 %><span class="it"><%= ++ln2 %></span><%= Util.htmlize(file2[j]) %><br/><% 287 } 288 } 289 %></td> 290 </tr><% 291 ln1 = cn1; 292 } 293 if (cn1 <= cl1) { 294 %> 295 <tr class="chunk"><td><% 296 for (int j = cn1; j <= cl1 ; j++) { 297 %><del class="d"><%= ++ln1 %></del><%= file1[j] 298 %><br/><% 299 } 300 %></td> 301 </tr><% 302 } 303 if (cn2 <= cl2) { 304 %> 305 <tr class="k<% 306 if (cn1 > cl1) { 307 %> chunk<% 308 } 309 %>"><td><% 310 for (int j = cn2; j < cl2; j++) { 311 %><span class="a it"><%= ++ln2 %></span><%= file2[j] 312 %><br/><% 313 } 314 %><span class="a it"><%= ++ln2 %></span><%= file2[cl2] %><% 315 if(full) { 316 %><a name="<%= ln2 %>" /><% 317 } 318 %></td> 319 </tr><% 320 } 321 } else if (type == DiffType.SIDEBYSIDE) { 322// SDIFF 323 if (cn1 > ln1 || cn2 > ln2) { 324 %> 325 <tr class="k"><td><% 326 if (full || cn2 - ln2 < 20) { 327 for (int j = ln1; j < cn1; j++) { 328 %><span class="it"><%= ++ln1 %></span><%= 329 Util.htmlize(file1[j]) %><br/><% 330 } 331 %></td><td><% 332 for (int j = ln2; j < cn2 ; j++) { 333 %><span class="it"><%= ++ln2 %></span><%= 334 Util.htmlize(file2[j]) %><br/><% 335 } 336 } else { 337 for (int j = ln1; j < ln1 + 8; j++) { 338 %><span class="it"><%= j+1 %></span><%= 339 Util.htmlize(file1[j]) %><br/><% 340 } 341 %><br/>--- <strong><%= cn1 - ln1 - 16 342 %> unchanged lines hidden</strong> (<a href="<%= reqURI 343%>?<%= QueryParameters.REVISION_1_PARAM_EQ %><%= rp1 %>& 344<%= QueryParameters.REVISION_2_PARAM_EQ %><%= rp2 %>& 345<%= QueryParameters.FORMAT_PARAM_EQ %><%= type.getAbbrev() %>& 346<%= QueryParameters.DIFF_LEVEL_PARAM_EQ %>1#<%= ln2 %>">view full</a>) 347 --- <br/><br/><% 348 ln1 = cn1 - 8; 349 for (int j = ln1; j < cn1; j++) { 350 %><span class="it"><%= ++ln1 %></span><%= 351 Util.htmlize(file1[j]) %><br/><% 352 } 353 %></td><td><% 354 for (int j = ln2; j < ln2 + 8; j++) { 355 %><span class="it"><%= j+1 %></span><%= 356 Util.htmlize(file2[j]) %><br/><% 357 } 358 %><br/>--- <strong><%= cn2 - ln2 - 16 359 %> unchanged lines hidden</strong> (<a href="<%= reqURI 360%>?<%= QueryParameters.REVISION_1_PARAM_EQ %><%= rp1 %>& 361<%= QueryParameters.REVISION_2_PARAM_EQ %><%= rp2 %>& 362<%= QueryParameters.FORMAT_PARAM_EQ %><%= type.getAbbrev() %>& 363<%= QueryParameters.DIFF_LEVEL_PARAM_EQ %>1#<%= ln2 %>">view full</a>) 364 --- <br/><br/><% 365 ln2 = cn2 - 8; 366 for (int j = ln2; j < cn2; j++) { 367 %><span class="it"><%= ++ln2 %></span><%= 368 Util.htmlize(file2[j]) %><br/><% 369 } 370 } 371 %></td> 372 </tr><% 373 } 374 %> 375 <tr class="k chunk"><td><% 376 for (int j = cn1; j <= cl1; j++) { 377 %><span class="it"><%= ++ln1 %></span><%= file1[j] %><br/><% 378 } 379 %></td><td><% 380 for (int j = cn2; j <= cl2; j++) { 381 %><span class="it"><%= ++ln2 %></span><a name="<%= ln2 %>"></a><%= 382 file2[j] %><br/><% 383 } 384 %></td> 385 </tr><% 386// OLD 387 } else if (type == DiffType.OLD) { 388 // OLD 389 if (cn1 > ln1) { 390 if (full || cn1 - ln1 < 20) { 391 for (int j = ln1; j < cn1; j++) { 392 %><span class="it"><%= ++ln1 %></span><%= 393 Util.htmlize(file1[j]) %><br/><% 394 } 395 } else { 396 for (int j = ln1; j < ln1 + 8; j++) { 397 %><span class="it"><%= j+1 %></span><%= 398 Util.htmlize(file1[j]) %><br/><% 399 } 400 %><br/>--- <strong><%= cn1 - ln1 - 16 401 %> unchanged lines hidden</strong> (<a href="<%= reqURI 402%>?<%= QueryParameters.REVISION_1_PARAM_EQ %><%= rp1 %>& 403<%= QueryParameters.REVISION_2_PARAM_EQ %><%= rp2 %>& 404<%= QueryParameters.FORMAT_PARAM_EQ %><%= type.getAbbrev() %>& 405<%= QueryParameters.DIFF_LEVEL_PARAM_EQ %>1#<%=ln1%>">view full</a>) --- <br/><br/><% 406 ln1 = cn1 - 8; 407 for (int j = ln1; j < cn1; j++) { 408 %><span class="it"><%= ++ln1 %></span><%= 409 Util.htmlize(file1[j]) %><br/><% 410 } 411 } 412 } 413 for (int j = cn1; j <= cl1 ; j++) { 414 %><span class="it"><%= ++ln1 %></span><%= file1[j] %><br/><% 415 } 416 if (full) { 417 %><a name="<%=ln1%>" ></a><% 418 } 419// NEW 420 } else if (type == DiffType.NEW) { 421 if (cn2 > ln2) { 422 if (full || cn2 - ln2 < 20) { 423 for (int j = ln2; j < cn2 ; j++) { 424 %><span class="it"><%= ++ln2 %></span><%= 425 Util.htmlize(file2[j]) %><br/><% 426 } 427 } else { 428 for (int j = ln2; j < ln2 + 8; j++) { 429 %><span class="it"><%= j+1 %></span><%= 430 Util.htmlize(file2[j]) %><br/><% 431 } 432 %><br/>--- <strong><%= cn2 - ln2 - 16 433 %> unchanged lines hidden</strong> (<a href="<%= reqURI 434%>?<%= QueryParameters.REVISION_1_PARAM_EQ %><%= rp1 %>& 435<%= QueryParameters.REVISION_2_PARAM_EQ %><%= rp2 %>& 436<%= QueryParameters.FORMAT_PARAM_EQ %><%= type.getAbbrev() %>& 437<%= QueryParameters.DIFF_LEVEL_PARAM_EQ %>1#<%= ln2 %>">view full</a>) --- <br/><br/><% 438 ln2 = cn2 - 8; 439 for (int j = ln2; j < cn2; j++) { 440 %><span class="it"><%= ++ln2 %></span><%= 441 Util.htmlize(file2[j]) %><br/><% 442 } 443 } 444 } 445 for (int j = cn2; j <= cl2 ; j++) { 446 %><span class="it"><%= ++ln2 %></span><%= file2[j] %><br/><% 447 } 448 if (full) { 449 %><a name="<%= ln2 %>"></a><% 450 } 451 } 452 } // else 453 } // for 454// deltas done, dump the remaining 455 if (file1.length >= ln1) { 456 if (type == DiffType.SIDEBYSIDE) { 457 if (full || file1.length - ln1 < 20) { 458 %> 459 <tr><td><% 460 for (int j = ln1; j < file1.length ; j++) { 461 %><span class="it"><%= j+1 %></span><%= Util.htmlize(file1[j]) %><br/><% 462 } 463 %></td><td><% 464 for (int j = ln2; j < file2.length ; j++) { 465 %><span class="it"><%= j+1 %></span><%= Util.htmlize(file2[j]) %><br/><% 466 } 467 %></td> 468 </tr> 469 </tbody> 470 </table><% 471 } else { 472 %> 473 <tr><td><% 474 for (int j = ln1; j < ln1 + 8 ; j++) { 475 %><span class="it"><%= j+1 %></span><%= Util.htmlize(file1[j]) %><br/><% 476 } 477 %><br/> --- <strong><%= file1.length - ln1 - 8 478 %> unchanged lines hidden</strong> --- </td><td><% 479 for (int j = ln2; j < ln2 + 8 ; j++) { 480 %><span class="it"><%= j+1 %></span><%= Util.htmlize(file2[j]) %><br/><% 481 } 482 %><br/>--- <strong><%= file1.length - ln1 - 8 483 %> unchanged lines hidden</strong> ---</td> 484 </tr> 485 </tbody> 486 </table><% 487 } 488 } else if (type == DiffType.UNIFIED) { 489 if (full || file2.length - ln2 < 20) { 490 %> 491 <tr><td><% 492 for (int j = ln2; j < file2.length ; j++) { 493 %><span class="it"><%= j+1 %></span><%= Util.htmlize(file2[j]) %><br/><% 494 } 495 %></td> 496 </tr> 497 </tbody> 498 </table><% 499 } else { 500 %> 501 <tr><td><% 502 for (int j = ln2; j < ln2 + 8 ; j++) { 503 %><span class="it"><%= j+1 %></span><%= Util.htmlize(file2[j]) %><br/><% 504 } 505 %><br/>--- <strong><%= file2.length - ln2 - 8 506 %> unchanged lines hidden</strong> ---</td> 507 </tr> 508 </tbody> 509 </table><% 510 } 511 } else if (type == DiffType.OLD) { 512 if (full || file1.length - ln1 < 20) { 513 for (int j = ln1; j < file1.length ; j++) { 514 %><span class="it"><%= j+1 %></span><%= Util.htmlize(file1[j]) %><br/><% 515 } 516 } else { 517 for (int j = ln1; j < ln1 + 8 ; j++) { 518 %><span class="it"><%= j+1 %></span><%= Util.htmlize(file1[j]) %><br/><% 519 } 520 %><br/> --- <strong><%= file1.length - ln1 - 8 521 %> unchanged lines hidden</strong> ---<br/><% 522 } 523 } else if (type == DiffType.NEW) { 524 if (full || file2.length - ln2 < 20) { 525 for (int j = ln2; j < file2.length ; j++) { 526 %><span class="it"><%= j+1 %></span><%=Util.htmlize(file2[j])%><br/><% 527 } 528 } else { 529 for (int j = ln2; j < ln2 + 8 ; j++) { 530 %><span class="it"><%= j+1 %></span><%= Util.htmlize(file2[j]) %><br/><% 531 } 532 %><br/> --- <strong><%= file2.length - ln2 - 8 533 %> unchanged lines hidden</strong> ---<br/><% 534 } 535 } 536 } 537 538//----DIFFS Done-------- 539 %></div> 540</div><% 541 } 542} 543/* ---------------------- diff.jsp end --------------------- */ 544%><%@ 545 546include file="foot.jspf" 547 548%> 549