💾 Archived View for lists.flounder.online › patches › threads › 20210322223344.6568-1-johann@qwertqw… captured on 2022-04-28 at 19:24:32. Gemini links have been rewritten to link to archived content
-=-=-=-=-=-=-
From: johann@qwertqwefsday.eu
Date: Mon, 22 Mar 2021 23:33:43 +0100
Message-Id: 20210322223344.6568-1-johann@qwertqwefsday.eu
To: <~aw/patches@lists.sr.ht>
Cc: "Johann150" <johann@qwertqwefsday.eu>
--------------------------------------
From: Johann150 <johann@qwertqwefsday.eu>
This shouldn't introduce path traversal bugs because we are only putting the
path into git and never into the file system. In bare repositories the files
would not even exist on disk (at least not under those names), so putting
the paths into the file system wouldn't work anyway.
---
src/main.rs | 70 ++++++++++++++++++++++++++-------------------
templates/tree.html | 2 +-
2 files changed, 42 insertions(+), 30 deletions(-)
diff --git a/src/main.rs b/src/main.rs
index 146e764..4490fb7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -290,8 +290,10 @@ async fn repo_refs(req: Request<()>) -> tide::Result {
struct RepoTreeTemplate<'a> {
repo: &'a Repository,
tree: Tree<'a>,
+ path: &'a Path,
spec: &'a str,
}
+
async fn repo_tree(req: Request<()>) -> tide::Result {
// TODO handle subtrees
let repo = repo_from_request(&req.param("repo_name")?)?;
@@ -310,6 +312,7 @@ async fn repo_tree(req: Request<()>) -> tide::Result {
let tmpl = RepoTreeTemplate {
repo: &repo,
tree,
+ path: Path::new(""),
spec,
};
Ok(tmpl.into())
@@ -367,12 +370,13 @@ async fn repo_file(req: Request<()>) -> tide::Result {
let spec = req.param("ref").ok().or_else(|| head.shorthand()).unwrap();
let commit = repo.revparse_single(spec)?.peel_to_commit()?;
let tree = commit.tree()?;
- let tree_entry = tree.get_name(req.param("object_name")?).unwrap();
+ let path = Path::new(req.param("object_name")?);
+ let tree_entry = tree.get_path(path).unwrap();
// TODO make sure I am escaping html properly here
// TODO allow disabling of syntax highlighting
// TODO -- dont pull in memory, use iterators if possible
let syntax_set = SyntaxSet::load_defaults_nonewlines();
- let extension = std::path::Path::new(tree_entry.name().unwrap())
+ let extension = path
.extension()
.and_then(std::ffi::OsStr::to_str)
.unwrap_or_default();
@@ -381,34 +385,42 @@ async fn repo_file(req: Request<()>) -> tide::Result {
.unwrap_or_else(|| syntax_set.find_syntax_plain_text());
let ts = ThemeSet::load_defaults();
let theme = &ts.themes["InspiredGitHub"]; // TODO make customizable
- let tree_obj = tree_entry.to_object(&repo)?;
- if tree_obj.as_tree().is_some() {
- // TODO render tree
- }
- let file_string = str::from_utf8(tree_obj.as_blob().unwrap().content())?;
- let mut highlighter = syntect::easy::HighlightLines::new(&syntax_reference, &theme);
- let (mut output, bg) = syntect::html::start_highlighted_html_snippet(&theme);
- for (n, line) in syntect::util::LinesWithEndings::from(file_string).enumerate() {
- let regions = highlighter.highlight(line, &syntax_set);
- output.push_str(&format!(
- "<a href='#L{0}' id='L{0}' class='line'>{0}</a>",
- n + 1
- ));
- syntect::html::append_highlighted_html_for_styled_line(
- ®ions[..],
- syntect::html::IncludeBackground::IfDifferent(bg),
- &mut output,
- );
- }
- output.push_str("</pre>\n");
+ let tmpl = match tree_entry.to_object(&repo)?.into_tree() {
+ Ok(tree) => RepoTreeTemplate {
+ repo: &repo,
+ tree,
+ path,
+ spec: &spec,
+ }
+ .into(),
+ Err(tree_obj) => {
+ let file_string = str::from_utf8(tree_obj.as_blob().unwrap().content())?;
+ let mut highlighter = syntect::easy::HighlightLines::new(&syntax_reference, &theme);
+ let (mut output, bg) = syntect::html::start_highlighted_html_snippet(&theme);
+ for (n, line) in syntect::util::LinesWithEndings::from(file_string).enumerate() {
+ let regions = highlighter.highlight(line, &syntax_set);
+ output.push_str(&format!(
+ "<a href='#L{0}' id='L{0}' class='line'>{0}</a>",
+ n + 1
+ ));
+ syntect::html::append_highlighted_html_for_styled_line(
+ ®ions[..],
+ syntect::html::IncludeBackground::IfDifferent(bg),
+ &mut output,
+ );
+ }
+ output.push_str("</pre>\n");
- let tmpl = RepoFileTemplate {
- repo: &repo,
- tree_entry: &tree_entry,
- file_text: &output,
- spec: &spec,
+ RepoFileTemplate {
+ repo: &repo,
+ tree_entry: &tree_entry,
+ file_text: &output,
+ spec: &spec,
+ }
+ .into()
+ }
};
- Ok(tmpl.into())
+ Ok(tmpl)
}
mod filters {
@@ -490,7 +502,7 @@ async fn main() -> Result<(), std::io::Error> {
app.at("/:repo_name/log/:ref").get(repo_log); // ref optional
app.at("/:repo_name/tree").get(repo_tree);
app.at("/:repo_name/tree/:ref").get(repo_tree);
- app.at("/:repo_name/tree/:ref/item/:object_name")
+ app.at("/:repo_name/tree/:ref/item/*object_name")
.get(repo_file);
// Raw files, patch files
app.listen(format!("[::]:{}", CONFIG.port)).await?;
diff --git a/templates/tree.html b/templates/tree.html
index 8e187f9..836e847 100644
--- a/templates/tree.html
+++ b/templates/tree.html
@@ -11,7 +11,7 @@
{{ entry.filemode()|unix_perms }}
</td>
<td class="filename">
- <a href="/{{repo|repo_name|urlencode_strict}}/tree/{{ spec }}/item/{{entry.name().unwrap()}}">
+ <a href="/{{repo|repo_name|urlencode_strict}}/tree/{{ spec }}/item/{{path.join(entry.name().unwrap()).to_string_lossy()}}">
{{ entry.name().unwrap() }}{% if entry.to_object(repo).unwrap().as_tree().is_some() %}/{% endif %}</a>
</td>
<td class="filesize">
--
2.20.1
From: alex@alexwennerberg.com
Date: Mon, 22 Mar 2021 17:53:33 -0700
Message-Id: CA4BJABOSCZY.3MFZ3PUK0YIV@debian-alex
To: "Johann Galle" <johann@qwertqwefsday.eu>, <~aw/patches@lists.sr.ht>
In-Reply-To: 20210322223344.6568-1-johann@qwertqwefsday.eu
--------------------------------------
Thank you!