10d40e9d0SAdam Hornáček<%-- 20d40e9d0SAdam HornáčekCDDL HEADER START 30d40e9d0SAdam Hornáček 40d40e9d0SAdam HornáčekThe contents of this file are subject to the terms of the 50d40e9d0SAdam HornáčekCommon Development and Distribution License (the "License"). 60d40e9d0SAdam HornáčekYou may not use this file except in compliance with the License. 70d40e9d0SAdam Hornáček 80d40e9d0SAdam HornáčekSee LICENSE.txt included in this distribution for the specific 90d40e9d0SAdam Hornáčeklanguage governing permissions and limitations under the License. 100d40e9d0SAdam Hornáček 110d40e9d0SAdam HornáčekWhen distributing Covered Code, include this CDDL HEADER in each 120d40e9d0SAdam Hornáčekfile and include the License file at LICENSE.txt. 130d40e9d0SAdam HornáčekIf applicable, add the following below this CDDL HEADER, with the 140d40e9d0SAdam Hornáčekfields enclosed by brackets "[]" replaced with your own identifying 150d40e9d0SAdam Hornáčekinformation: Portions Copyright [yyyy] [name of copyright owner] 160d40e9d0SAdam Hornáček 170d40e9d0SAdam HornáčekCDDL HEADER END 180d40e9d0SAdam Hornáček 19b13c5a0eSAdam HornacekCopyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. 200d40e9d0SAdam HornáčekPortions Copyright 2011 Jens Elkner. 215c931ce8SChris FrairePortions Copyright (c) 2017-2020, Chris Fraire <cfraire@me.com>. 220d40e9d0SAdam Hornáček 230d40e9d0SAdam Hornáček--%> 240d40e9d0SAdam Hornáček<%@page errorPage="error.jsp" import=" 250d40e9d0SAdam Hornáčekjava.io.BufferedInputStream, 261c830032SChris Frairejava.io.File, 270d40e9d0SAdam Hornáčekjava.io.FileInputStream, 280d40e9d0SAdam Hornáčekjava.io.InputStreamReader, 291c830032SChris Frairejava.io.IOException, 300d40e9d0SAdam Hornáčekjava.io.Reader, 310d40e9d0SAdam Hornáčekjava.net.URLEncoder, 320d40e9d0SAdam Hornáčekjava.nio.charset.StandardCharsets, 330d40e9d0SAdam Hornáčekjava.util.List, 3452dccac1SChris Frairejava.util.Locale, 35e829566cSChris Frairejava.util.logging.Level, 36e829566cSChris Frairejava.util.logging.Logger, 375c931ce8SChris Frairejava.util.Set, 385c931ce8SChris Frairejava.util.TreeSet, 39686556f2SAdam Hornáčekorg.opengrok.indexer.analysis.AnalyzerGuru, 40686556f2SAdam Hornáčekorg.opengrok.indexer.analysis.Definitions, 41e829566cSChris Fraireorg.opengrok.indexer.analysis.AbstractAnalyzer, 42e829566cSChris Fraireorg.opengrok.indexer.analysis.AnalyzerFactory, 4341351de3SChris Fraireorg.opengrok.indexer.analysis.NullableNumLinesLOC, 44686556f2SAdam Hornáčekorg.opengrok.indexer.history.Annotation, 45686556f2SAdam Hornáčekorg.opengrok.indexer.index.IndexDatabase, 46e829566cSChris Fraireorg.opengrok.indexer.logger.LoggerFactory, 47686556f2SAdam Hornáčekorg.opengrok.indexer.search.DirectoryEntry, 48686556f2SAdam Hornáčekorg.opengrok.indexer.search.DirectoryExtraReader, 49686556f2SAdam Hornáčekorg.opengrok.indexer.util.FileExtraZipper, 507d004396SChris Fraireorg.opengrok.indexer.util.ForbiddenSymlinkException, 51686556f2SAdam Hornáčekorg.opengrok.indexer.util.IOUtils, 5256f072caSAdam Hornáčekorg.opengrok.web.DirectoryListing, 53686556f2SAdam Hornáčekorg.opengrok.indexer.web.SearchHelper" 5457eefa47SKryštof Tulinger%> 557af88e20SVladimir Kotal<%@ page import="static org.opengrok.web.PageConfig.DUMMY_REVISION" %> 56*ae1c323bSVladimir Kotal<%@ page import="org.opengrok.indexer.web.SortOrder" %> 57*ae1c323bSVladimir Kotal<%@ page import="jakarta.servlet.http.Cookie" %> 5857eefa47SKryštof Tulinger<% 590d40e9d0SAdam Hornáček{ 600d40e9d0SAdam Hornáček // need to set it here since requesting parameters 610d40e9d0SAdam Hornáček if (request.getCharacterEncoding() == null) { 620d40e9d0SAdam Hornáček request.setCharacterEncoding("UTF-8"); 630d40e9d0SAdam Hornáček } 640d40e9d0SAdam Hornáček 650d40e9d0SAdam Hornáček PageConfig cfg = PageConfig.get(request); 660d40e9d0SAdam Hornáček cfg.checkSourceRootExistence(); 670d40e9d0SAdam Hornáček 6855774b8bSChris Fraire String rev = cfg.getRequestedRevision(); 6955774b8bSChris Fraire if (!cfg.isDir() && rev.length() == 0) { 7055774b8bSChris Fraire /* 7155774b8bSChris Fraire * Get the latest revision and redirect so that the revision number 7255774b8bSChris Fraire * appears in the URL. 7355774b8bSChris Fraire */ 7496b0c142SChris Fraire String latestRevision = cfg.getLatestRevision(); 7596b0c142SChris Fraire if (latestRevision != null) { 76eeb95924SChris Fraire cfg.evaluateMatchOffset(); 7796b0c142SChris Fraire String location = cfg.getRevisionLocation(latestRevision); 7855774b8bSChris Fraire response.sendRedirect(location); 7955774b8bSChris Fraire return; 8055774b8bSChris Fraire } 8155774b8bSChris Fraire if (!cfg.getEnv().isGenerateHtml()) { 82eeb95924SChris Fraire cfg.evaluateMatchOffset(); 8355774b8bSChris Fraire /* 8455774b8bSChris Fraire * Economy mode is on and failed to get the last revision 8555774b8bSChris Fraire * (presumably running with history turned off). Use dummy 8655774b8bSChris Fraire * revision string so that xref can be generated from the resource 8755774b8bSChris Fraire * file directly. 8855774b8bSChris Fraire */ 8996b0c142SChris Fraire String location = cfg.getRevisionLocation(DUMMY_REVISION); 9055774b8bSChris Fraire response.sendRedirect(location); 9155774b8bSChris Fraire return; 9255774b8bSChris Fraire } 93eeb95924SChris Fraire 94eeb95924SChris Fraire if (cfg.evaluateMatchOffset()) { 95eeb95924SChris Fraire /* 96eeb95924SChris Fraire * If after calling, a match offset has been translated to a 97eeb95924SChris Fraire * fragment identifier (specifying a line#), then redirect to self. 98eeb95924SChris Fraire * This block will not be activated again the second time. 99eeb95924SChris Fraire */ 100eeb95924SChris Fraire String location = cfg.getRevisionLocation(""); // empty 10155774b8bSChris Fraire response.sendRedirect(location); 10255774b8bSChris Fraire return; 10355774b8bSChris Fraire } 10455774b8bSChris Fraire } 10555774b8bSChris Fraire 1060d40e9d0SAdam Hornáček Annotation annotation = cfg.getAnnotation(); 1070d40e9d0SAdam Hornáček if (annotation != null) { 1080d40e9d0SAdam Hornáček int r = annotation.getWidestRevision(); 1090d40e9d0SAdam Hornáček int a = annotation.getWidestAuthor(); 1100d40e9d0SAdam Hornáček cfg.addHeaderData("<style type=\"text/css\">" 1110d40e9d0SAdam Hornáček + ".blame .r { width: " + (r == 0 ? 6 : Math.ceil(r * 0.7)) + "em; } " 1120d40e9d0SAdam Hornáček + ".blame .a { width: " + (a == 0 ? 6 : Math.ceil(a * 0.7)) + "em; } " 1130d40e9d0SAdam Hornáček + "</style>"); 1140d40e9d0SAdam Hornáček } 1150d40e9d0SAdam Hornáček} 1160d40e9d0SAdam Hornáček%><%@include 1170d40e9d0SAdam Hornáček 1180d40e9d0SAdam Hornáčekfile="mast.jsp" 1190d40e9d0SAdam Hornáček 1200d40e9d0SAdam Hornáček%><script type="text/javascript">/* <![CDATA[ */ 1210d40e9d0SAdam Hornáčekdocument.pageReady.push(function() { pageReadyList();}); 1220d40e9d0SAdam Hornáček/* ]]> */</script> 1230d40e9d0SAdam Hornáček<% 1240d40e9d0SAdam Hornáček/* ---------------------- list.jsp start --------------------- */ 1250d40e9d0SAdam Hornáček{ 126e829566cSChris Fraire final Logger LOGGER = LoggerFactory.getLogger(getClass()); 127e829566cSChris Fraire 1280d40e9d0SAdam Hornáček PageConfig cfg = PageConfig.get(request); 1290d40e9d0SAdam Hornáček String rev = cfg.getRequestedRevision(); 130e393cb49SAdam Hornáček Project project = cfg.getProject(); 1310d40e9d0SAdam Hornáček 132e393cb49SAdam Hornáček String navigateWindowEnabled = project != null ? Boolean.toString( 133e393cb49SAdam Hornáček project.isNavigateWindowEnabled()) : "false"; 1340d40e9d0SAdam Hornáček File resourceFile = cfg.getResourceFile(); 1350d40e9d0SAdam Hornáček String path = cfg.getPath(); 1360d40e9d0SAdam Hornáček String basename = resourceFile.getName(); 1370d40e9d0SAdam Hornáček String rawPath = request.getContextPath() + Prefix.DOWNLOAD_P + path; 1380d40e9d0SAdam Hornáček Reader r = null; 1390d40e9d0SAdam Hornáček if (cfg.isDir()) { 1400d40e9d0SAdam Hornáček // valid resource is requested 1410d40e9d0SAdam Hornáček // mast.jsp assures, that resourceFile is valid and not / 1420d40e9d0SAdam Hornáček // see cfg.resourceNotAvailable() 1430d40e9d0SAdam Hornáček String cookieValue = cfg.getRequestedProjectsAsString(); 1445c931ce8SChris Fraire String projectName = null; 145e393cb49SAdam Hornáček if (project != null) { 1465c931ce8SChris Fraire projectName = project.getName(); 1470d40e9d0SAdam Hornáček Set<String> projects = cfg.getRequestedProjects(); 1485c931ce8SChris Fraire if (!projects.contains(projectName)) { 1495c931ce8SChris Fraire projects.add(projectName); 1500d40e9d0SAdam Hornáček // update cookie 1515c931ce8SChris Fraire cookieValue = cookieValue.length() == 0 ? projectName : 1525c931ce8SChris Fraire projectName + ',' + cookieValue; 153b13c5a0eSAdam Hornacek Cookie cookie = new Cookie(PageConfig.OPEN_GROK_PROJECT, URLEncoder.encode(cookieValue, StandardCharsets.UTF_8)); 1540d40e9d0SAdam Hornáček // TODO hmmm, projects.jspf doesn't set a path 1550d40e9d0SAdam Hornáček cookie.setPath(request.getContextPath() + '/'); 1560d40e9d0SAdam Hornáček response.addCookie(cookie); 1570d40e9d0SAdam Hornáček } 1580d40e9d0SAdam Hornáček } 1590d40e9d0SAdam Hornáček // requesting a directory listing 1600d40e9d0SAdam Hornáček DirectoryListing dl = new DirectoryListing(cfg.getEftarReader()); 1610d40e9d0SAdam Hornáček List<String> files = cfg.getResourceFileList(); 1620d40e9d0SAdam Hornáček if (!files.isEmpty()) { 16341351de3SChris Fraire List<NullableNumLinesLOC> extras = null; 164*ae1c323bSVladimir Kotal SearchHelper searchHelper = cfg.prepareInternalSearch(SortOrder.RELEVANCY); 1655c931ce8SChris Fraire /* 1665c931ce8SChris Fraire * N.b. searchHelper.destroy() is called via 1675c931ce8SChris Fraire * WebappListener.requestDestroyed() on presence of the following 1685c931ce8SChris Fraire * REQUEST_ATTR. 1695c931ce8SChris Fraire */ 1700d40e9d0SAdam Hornáček request.setAttribute(SearchHelper.REQUEST_ATTR, searchHelper); 1715c931ce8SChris Fraire if (project != null) { 172e393cb49SAdam Hornáček searchHelper.prepareExec(project); 1735c931ce8SChris Fraire } else { 1745c931ce8SChris Fraire //noinspection Convert2Diamond 1755c931ce8SChris Fraire searchHelper.prepareExec(new TreeSet<String>()); 1765c931ce8SChris Fraire } 1770d40e9d0SAdam Hornáček 178*ae1c323bSVladimir Kotal if (searchHelper.getSearcher() != null) { 1795c931ce8SChris Fraire DirectoryExtraReader extraReader = new DirectoryExtraReader(); 1807d004396SChris Fraire String primePath = path; 1817d004396SChris Fraire try { 1825c931ce8SChris Fraire primePath = searchHelper.getPrimeRelativePath(projectName, path); 1837d004396SChris Fraire } catch (IOException | ForbiddenSymlinkException ex) { 1847d004396SChris Fraire LOGGER.log(Level.WARNING, String.format( 1857d004396SChris Fraire "Error getting prime relative for %s", path), ex); 1867d004396SChris Fraire } 187*ae1c323bSVladimir Kotal extras = extraReader.search(searchHelper.getSearcher(), primePath); 1880d40e9d0SAdam Hornáček } 1890d40e9d0SAdam Hornáček 1900d40e9d0SAdam Hornáček FileExtraZipper zipper = new FileExtraZipper(); 1917af88e20SVladimir Kotal List<DirectoryEntry> entries = zipper.zip(resourceFile, files, extras); 1920d40e9d0SAdam Hornáček 1937af88e20SVladimir Kotal List<String> readMes = dl.extraListTo(Util.URIEncodePath(request.getContextPath()), 1940d40e9d0SAdam Hornáček resourceFile, out, path, entries); 1950d40e9d0SAdam Hornáček File[] catfiles = cfg.findDataFiles(readMes); 1960d40e9d0SAdam Hornáček for (int i=0; i < catfiles.length; i++) { 1970d40e9d0SAdam Hornáček if (catfiles[i] == null) { 1980d40e9d0SAdam Hornáček continue; 1990d40e9d0SAdam Hornáček } 2000d40e9d0SAdam Hornáček%> 2010d40e9d0SAdam Hornáček<% 20252dccac1SChris Fraire String lcName = readMes.get(i).toLowerCase(Locale.ROOT); 2030d40e9d0SAdam Hornáček if (lcName.endsWith(".md") || lcName.endsWith(".markdown")) { 2040d40e9d0SAdam Hornáček %><div id="src<%=i%>" data-markdown> 2050d40e9d0SAdam Hornáček <div class="markdown-heading"> 2060d40e9d0SAdam Hornáček <h3><%= readMes.get(i) %></h3> 2070d40e9d0SAdam Hornáček </div> 2080d40e9d0SAdam Hornáček <div class="markdown-content" 2090d40e9d0SAdam Hornáček data-markdown-download="<%= request.getContextPath() + Prefix.DOWNLOAD_P + Util.URIEncodePath(cfg.getPath() + readMes.get(i)) %>"> 2100d40e9d0SAdam Hornáček </div> 2110d40e9d0SAdam Hornáček <pre data-markdown-original><% 2120d40e9d0SAdam Hornáček Util.dump(out, catfiles[i], catfiles[i].getName().endsWith(".gz")); 2130d40e9d0SAdam Hornáček %></pre> 2140d40e9d0SAdam Hornáček </div> 2150d40e9d0SAdam Hornáček<% } else { %> 2160d40e9d0SAdam Hornáček <h3><%= readMes.get(i) %></h3> 2170d40e9d0SAdam Hornáček <div id="src<%=i%>"> 2180d40e9d0SAdam Hornáček <pre><% 2190d40e9d0SAdam Hornáček Util.dump(out, catfiles[i], catfiles[i].getName().endsWith(".gz")); 2200d40e9d0SAdam Hornáček %></pre> 2210d40e9d0SAdam Hornáček </div> 2220d40e9d0SAdam Hornáček<% 2230d40e9d0SAdam Hornáček } 2240d40e9d0SAdam Hornáček 2250d40e9d0SAdam Hornáček } 2260d40e9d0SAdam Hornáček } 227a03922c4SAdam Hornáček } else if (rev.length() != 0) { 228a03922c4SAdam Hornáček // requesting a revision 22955774b8bSChris Fraire File xrefFile; 2301532fde5SVladimir Kotal if (cfg.isLatestRevision(rev) && (xrefFile = cfg.findDataFile()) != null) { 231a03922c4SAdam Hornáček if (cfg.annotate()) { 2320d40e9d0SAdam Hornáček // annotate 2331532fde5SVladimir Kotal BufferedInputStream bin = new BufferedInputStream(new FileInputStream(resourceFile)); 2340d40e9d0SAdam Hornáček try { 23557eefa47SKryštof Tulinger AnalyzerFactory a = AnalyzerGuru.find(basename); 23657eefa47SKryštof Tulinger AbstractAnalyzer.Genre g = AnalyzerGuru.getGenre(a); 2370d40e9d0SAdam Hornáček if (g == null) { 2380d40e9d0SAdam Hornáček a = AnalyzerGuru.find(bin); 2390d40e9d0SAdam Hornáček g = AnalyzerGuru.getGenre(a); 2400d40e9d0SAdam Hornáček } 24157eefa47SKryštof Tulinger if (g == AbstractAnalyzer.Genre.IMAGE) { 2420d40e9d0SAdam Hornáček%> 2430d40e9d0SAdam Hornáček<div id="src"> 2441c830032SChris Fraire <img src="<%= rawPath %>" alt="Image from Source Repository"/> 2450d40e9d0SAdam Hornáček</div><% 24657eefa47SKryštof Tulinger } else if ( g == AbstractAnalyzer.Genre.HTML) { 2477af88e20SVladimir Kotal /* 2480d40e9d0SAdam Hornáček * For backward compatibility, read the OpenGrok-produced 2490d40e9d0SAdam Hornáček * document using the system default charset. 2500d40e9d0SAdam Hornáček */ 2510d40e9d0SAdam Hornáček r = new InputStreamReader(bin); 252e393cb49SAdam Hornáček // dumpXref() is also useful here for translating links. 253e393cb49SAdam Hornáček Util.dumpXref(out, r, request.getContextPath()); 25457eefa47SKryštof Tulinger } else if (g == AbstractAnalyzer.Genre.PLAIN) { 2550d40e9d0SAdam Hornáček%> 2560d40e9d0SAdam Hornáček<div id="src" data-navigate-window-enabled="<%= navigateWindowEnabled %>"> 2570d40e9d0SAdam Hornáček <pre><% 2580d40e9d0SAdam Hornáček // We're generating xref for the latest revision, so we can 2590d40e9d0SAdam Hornáček // find the definitions in the index. 2600d40e9d0SAdam Hornáček Definitions defs = IndexDatabase.getDefinitions(resourceFile); 2610d40e9d0SAdam Hornáček Annotation annotation = cfg.getAnnotation(); 2624c692fbfSVladimir Kotal // Data under source root is read with UTF-8 as a default. 2630d40e9d0SAdam Hornáček r = IOUtils.createBOMStrippedReader(bin, 2640d40e9d0SAdam Hornáček StandardCharsets.UTF_8.name()); 265e393cb49SAdam Hornáček AnalyzerGuru.writeDumpedXref(request.getContextPath(), a, 266e393cb49SAdam Hornáček r, out, defs, annotation, project); 2670d40e9d0SAdam Hornáček %></pre> 2680d40e9d0SAdam Hornáček</div><% 2690d40e9d0SAdam Hornáček } else { 2700d40e9d0SAdam Hornáček%> 2710d40e9d0SAdam HornáčekClick <a href="<%= rawPath %>">download <%= basename %></a><% 2720d40e9d0SAdam Hornáček } 2730d40e9d0SAdam Hornáček } finally { 2740d40e9d0SAdam Hornáček if (r != null) { 275963a3f81SChris Fraire IOUtils.close(r); 276963a3f81SChris Fraire bin = null; 2770d40e9d0SAdam Hornáček } 2780d40e9d0SAdam Hornáček if (bin != null) { 279963a3f81SChris Fraire IOUtils.close(bin); 280963a3f81SChris Fraire bin = null; 2810d40e9d0SAdam Hornáček } 2820d40e9d0SAdam Hornáček } 283a03922c4SAdam Hornáček 284a03922c4SAdam Hornáček } else { 2850d40e9d0SAdam Hornáček%> 2860d40e9d0SAdam Hornáček<div id="src" data-navigate-window-enabled="<%= navigateWindowEnabled %>"> 2870d40e9d0SAdam Hornáček <pre><% 288e393cb49SAdam Hornáček boolean compressed = xrefFile.getName().endsWith(".gz"); 289e393cb49SAdam Hornáček Util.dumpXref(out, xrefFile, compressed, 290e393cb49SAdam Hornáček request.getContextPath()); 2910d40e9d0SAdam Hornáček %></pre> 2927af88e20SVladimir Kotal</div> 2937af88e20SVladimir Kotal<% 2940d40e9d0SAdam Hornáček } 2950d40e9d0SAdam Hornáček } else { 2960d40e9d0SAdam Hornáček%> 2977af88e20SVladimir Kotal<%@ 2987af88e20SVladimir Kotal 2997af88e20SVladimir Kotalinclude file="xref.jspf" 3007af88e20SVladimir Kotal 3010d40e9d0SAdam Hornáček%> 3027af88e20SVladimir Kotal<% 3030d40e9d0SAdam Hornáček } 3040d40e9d0SAdam Hornáček } else { 3054c692fbfSVladimir Kotal // Requesting cross referenced file with no known revision. 30655774b8bSChris Fraire File xrefFile = cfg.findDataFile(); 3070d40e9d0SAdam Hornáček if (xrefFile != null) { 3080d40e9d0SAdam Hornáček%> 3090d40e9d0SAdam Hornáček<div id="src" data-navigate-window-enabled="<%= navigateWindowEnabled %>"> 3100d40e9d0SAdam Hornáček <pre><% 311e393cb49SAdam Hornáček boolean compressed = xrefFile.getName().endsWith(".gz"); 312e393cb49SAdam Hornáček Util.dumpXref(out, xrefFile, compressed, request.getContextPath()); 3130d40e9d0SAdam Hornáček %></pre> 3147af88e20SVladimir Kotal</div> 3157af88e20SVladimir Kotal<% 31617c862aeSVladimir Kotal } else { 3177af88e20SVladimir Kotal // Failed to get xref, generate on the fly. 31817c862aeSVladimir Kotal%> 3197af88e20SVladimir Kotal<%@ 3207af88e20SVladimir Kotal 3217af88e20SVladimir Kotalinclude file="xref.jspf" 3227af88e20SVladimir Kotal 3237af88e20SVladimir Kotal%> 3247af88e20SVladimir Kotal<% 3250d40e9d0SAdam Hornáček } 3260d40e9d0SAdam Hornáček } 3270d40e9d0SAdam Hornáček} 3280d40e9d0SAdam Hornáček/* ---------------------- list.jsp end --------------------- */ 3290d40e9d0SAdam Hornáček%><%@ 3300d40e9d0SAdam Hornáček 3310d40e9d0SAdam Hornáčekinclude file="foot.jspf" 3320d40e9d0SAdam Hornáček 3330d40e9d0SAdam Hornáček%> 334