Skip to content

Commit

Permalink
Display html files in a sandboxed iframe
Browse files Browse the repository at this point in the history
  • Loading branch information
apardyl committed Jun 23, 2019
1 parent e4f9a08 commit 2439f09
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 3 deletions.
2 changes: 1 addition & 1 deletion detekt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ style:
active: true
ReturnCount:
active: true
max: 5
max: 10
excludedFunctions: "equals"
SafeCast:
active: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class WebSecurityConfig(
}
http.authorizeRequests().antMatchers(*allowUrls.toTypedArray()).permitAll()
.anyRequest().authenticated()
.and().headers().frameOptions().sameOrigin()
}

override fun configure(web: WebSecurity) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ class FilesystemController(
))
}

private fun previewPage(entity: RepositoryFile, path: String): ModelAndView {
return ModelAndView("preview_page", mapOf(
"raw" to "/raw/$path",
"path" to createBreadcrumb(entity),
"download" to "/download/${entity.relativePath}"
))
}

@Secured(Permission.READ_STR)
@GetMapping("/file/**")
fun fileIndex(request: HttpServletRequest): ModelAndView {
Expand All @@ -106,6 +114,7 @@ class FilesystemController(
return ModelAndView("tree", mapOf("children" to sortedChildren, "path" to createBreadcrumb(entity)))
} else if (entity is RepositoryFile) {
when {
entity.isPage -> return previewPage(entity, path)
entity.mimeType.startsWith("text/") || entity.isCode -> return previewText(entity)
entity.isDisplayableImage -> return previewImage(entity)
}
Expand All @@ -132,6 +141,24 @@ class FilesystemController(
response.flushBuffer()
}

@Secured(Permission.READ_STR)
@GetMapping("/raw/**")
fun raw(request: HttpServletRequest, response: HttpServletResponse) {
val path = request.servletPath.removePrefix("/raw/")
val entity = (repoService.getEntity(path)
?: throw NotFoundException(path)) as? RepositoryFile
?: throw BadRequestException("not a file")

response.contentType = entity.mimeType
response.setContentLengthLong(entity.file.length())

val stream = entity.file.inputStream()
stream.use {
IOUtils.copy(stream, response.outputStream)
}
response.flushBuffer()
}

@ExceptionHandler(value = [NotFoundException::class])
fun notFoundException(ex: NotFoundException): ModelAndView {
return ModelAndView("404", "path", ex.path)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ class RepositoryFile(
private val logger = LoggerFactory.getLogger(RepositoryFile::class.java)

private val displayableImageTypes = setOf(
// Based on: https://en.wikipedia.org/wiki/Comparison_of_web_browsers#Image_format_support
"image/png", "image/jpeg", "image/gif", "image/svg+xml"
// Based on: https://en.wikipedia.org/wiki/Comparison_of_web_browsers#Image_format_support
"image/png", "image/jpeg", "image/gif", "image/svg+xml"
)

private val safeMimetype = setOf(
Expand All @@ -45,6 +45,10 @@ class RepositoryFile(
"Makefile", "Dockerfile", "CMakeLists.txt"
// TODO: expand
)

private val pageFileNames = setOf(
"html", "htm"
)
}

val mimeType: String
Expand All @@ -64,6 +68,11 @@ class RepositoryFile(
return codeFileNames.contains(name) || codeFileExts.contains(FilenameUtils.getExtension(name))
}

val isPage: Boolean
get() {
return pageFileNames.contains(FilenameUtils.getExtension(name.toLowerCase()))
}

val isDisplayableImage: Boolean
get() {
return displayableImageTypes.contains(mimeType)
Expand Down
7 changes: 7 additions & 0 deletions src/main/resources/static/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,10 @@ code.hljs {
padding: 1px;
background-color: #fff;
}

.page-frame {
display: block;
width: 100%;
border: none;
outline: none;
}
40 changes: 40 additions & 0 deletions src/main/resources/templates/preview_page.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html lang="en"
layout:decorate="~{layout}">
<head>
<title>Mordor</title>
</head>
<body>
<div layout:fragment="content">
<ol class="breadcrumb">
<li th:each="dir, itrStat : ${path}" th:class="${itrStat.last}? 'breadcrumb-item active' : 'breadcrumb-item'">
<a th:unless="${itrStat.last}" th:href="${dir.path}" th:text="${dir.name}">directory</a>
<span th:if="${itrStat.last}" th:text="${dir.name}">current directory</span>
</li>
</ol>

<script>
function setIframeHeight(iframe) {
if (iframe) {
var iframeWin = iframe.contentWindow || iframe.contentDocument.parentWindow;
if (iframeWin.document.body) {
iframe.height = iframeWin.document.documentElement.scrollHeight || iframeWin.document.body.scrollHeight;
}
}
};
window.onload = function () {
setIframeHeight(document.getElementById('page-frame'));
};
</script>

<div class="card mt-2">
<div class="card-header">
<a href="#" th:href="@{${download}}" class="btn btn-secondary"><i class="fas fa-download"></i> Download</a>
</div>
<pre class="card-body p-0 m-0">
<iframe id="page-frame" class="page-frame" th:src="@{${raw}}" height="200" sandbox="allow-same-origin"></iframe>
</pre>
</div>
</div>
</body>
</html>

0 comments on commit 2439f09

Please sign in to comment.