Canonicalize template directory before globbing.

This prevents the glob from returning paths that don't include the root
template dir due to resolution of relative paths like `./foo`,
preventing #1541 from reoccurring. Furthermore, this prevents
misconfigured, non-existent template directories from silently passing
through, instead causing an error at init-time.
This commit is contained in:
Sergio Benitez 2021-02-19 12:50:03 -08:00
parent aaea84d750
commit 8ee581a697
4 changed files with 22 additions and 12 deletions

View File

@ -18,7 +18,15 @@ impl Context {
/// Load all of the templates at `root`, initialize them using the relevant /// Load all of the templates at `root`, initialize them using the relevant
/// template engine, and store all of the initialized state in a `Context` /// template engine, and store all of the initialized state in a `Context`
/// structure, which is returned if all goes well. /// structure, which is returned if all goes well.
pub fn initialize(root: PathBuf) -> Option<Context> { pub fn initialize(root: &Path) -> Option<Context> {
let root = match root.canonicalize() {
Ok(root) => root,
Err(e) => {
error!("Invalid template directory '{}': {}.", root.display(), e);
return None;
}
};
let mut templates: HashMap<String, TemplateInfo> = HashMap::new(); let mut templates: HashMap<String, TemplateInfo> = HashMap::new();
for ext in Engines::ENABLED_EXTENSIONS { for ext in Engines::ENABLED_EXTENSIONS {
let mut glob_path = root.join("**").join("*"); let mut glob_path = root.join("**").join("*");
@ -48,13 +56,12 @@ impl Context {
} }
Engines::init(&templates) Engines::init(&templates)
.map(|engines| Context { root, templates, engines } ) .map(|engines| Context { root: root.into(), templates, engines } )
} }
} }
/// Removes the file path's extension or does nothing if there is none. /// Removes the file path's extension or does nothing if there is none.
fn remove_extension<P: AsRef<Path>>(path: P) -> PathBuf { fn remove_extension(path: &Path) -> PathBuf {
let path = path.as_ref();
let stem = match path.file_stem() { let stem = match path.file_stem() {
Some(stem) => stem, Some(stem) => stem,
None => return path.to_path_buf() None => return path.to_path_buf()

View File

@ -103,7 +103,7 @@ mod context {
if changed { if changed {
info_!("Change detected: reloading templates."); info_!("Change detected: reloading templates.");
let mut ctxt = self.context_mut(); let mut ctxt = self.context_mut();
if let Some(mut new_ctxt) = Context::initialize(ctxt.root.clone()) { if let Some(mut new_ctxt) = Context::initialize(&ctxt.root) {
match callback(&mut new_ctxt.engines) { match callback(&mut new_ctxt.engines) {
Ok(()) => *ctxt = new_ctxt, Ok(()) => *ctxt = new_ctxt,
Err(e) => { Err(e) => {
@ -164,8 +164,7 @@ impl Fairing for TemplateFairing {
} }
}; };
let root = Source::from(&*path); match Context::initialize(&path) {
match Context::initialize(path) {
Some(mut ctxt) => { Some(mut ctxt) => {
use rocket::{logger::PaintExt, yansi::Paint}; use rocket::{logger::PaintExt, yansi::Paint};
use crate::templates::Engines; use crate::templates::Engines;
@ -174,7 +173,7 @@ impl Fairing for TemplateFairing {
match (self.callback)(&mut ctxt.engines) { match (self.callback)(&mut ctxt.engines) {
Ok(()) => { Ok(()) => {
info_!("directory: {}", Paint::white(root)); info_!("directory: {}", Paint::white(Source::from(&*path)));
info_!("engines: {:?}", Paint::white(Engines::ENABLED_EXTENSIONS)); info_!("engines: {:?}", Paint::white(Engines::ENABLED_EXTENSIONS));
Ok(rocket.manage(ContextManager::new(ctxt))) Ok(rocket.manage(ContextManager::new(ctxt)))
} }
@ -185,7 +184,10 @@ impl Fairing for TemplateFairing {
} }
} }
} }
None => Err(rocket), None => {
error_!("Launch will be aborted due to failed template initialization.");
Err(rocket)
}
} }
} }

View File

@ -352,7 +352,7 @@ impl Template {
/// ///
/// # Example /// # Example
/// ///
/// ```rust /// ```rust,no_run
/// # extern crate rocket; /// # extern crate rocket;
/// # extern crate rocket_contrib; /// # extern crate rocket_contrib;
/// use std::collections::HashMap; /// use std::collections::HashMap;

View File

@ -399,10 +399,11 @@ fairings. To attach the template fairing, simply call
# use rocket_contrib::templates::Template; # use rocket_contrib::templates::Template;
fn main() { #[launch]
fn rocket() -> _ {
rocket::ignite() rocket::ignite()
.mount("/", routes![/* .. */]) .mount("/", routes![/* .. */])
.attach(Template::fairing()); .attach(Template::fairing())
} }
``` ```