2023-03-08 07:00:05 +00:00
|
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2023 Emma Tebibyte <emma@tebibyte.media>
|
|
|
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
|
*
|
|
|
|
|
* This file is part of Plaque.
|
|
|
|
|
*
|
|
|
|
|
* Plaque is free software: you can redistribute it and/or modify it under the
|
|
|
|
|
* terms of the GNU Affero General Public License as published by the Free
|
|
|
|
|
* Software Foundation, either version 3 of the License, or (at your option) any
|
|
|
|
|
* later version.
|
|
|
|
|
*
|
|
|
|
|
* Plaque is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
|
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
|
|
|
* A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
|
|
|
* details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
|
|
|
* along with this program. If not, see https://www.gnu.org/licenses/.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
use std::{
|
|
|
|
|
env,
|
|
|
|
|
fs::File,
|
|
|
|
|
io::Read,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
use charsets::Charset;
|
|
|
|
|
use isolang::Language;
|
|
|
|
|
use serde::Deserialize;
|
|
|
|
|
use serde_with::{ serde_as, DisplayFromStr };
|
|
|
|
|
use toml::{ de::ValueDeserializer, Value };
|
|
|
|
|
use yacexits::*;
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize)]
|
|
|
|
|
pub struct Config {
|
|
|
|
|
pub content_dir: String,
|
|
|
|
|
pub output_dir: String,
|
|
|
|
|
pub template_dir: String,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[serde_as]
|
|
|
|
|
#[derive(Deserialize)]
|
|
|
|
|
pub struct PageMeta {
|
|
|
|
|
pub author: String,
|
|
|
|
|
|
|
|
|
|
pub date: String,
|
|
|
|
|
|
|
|
|
|
#[serde_as(as = "DisplayFromStr")]
|
|
|
|
|
pub encoding: Charset,
|
|
|
|
|
|
|
|
|
|
pub lang: Language,
|
|
|
|
|
|
|
|
|
|
pub template: String,
|
2023-03-13 22:41:22 +00:00
|
|
|
|
|
|
|
|
|
pub kind: String,
|
2023-03-08 07:00:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_path(xdg: &str) -> Result<String, (String, u32)> {
|
|
|
|
|
let dir: String;
|
2023-03-25 20:23:26 +00:00
|
|
|
|
let home_dir = match env::var("HOME").ok() {
|
|
|
|
|
Some(home) => home,
|
|
|
|
|
None => {
|
|
|
|
|
return Err((
|
|
|
|
|
"Unable to determine path to current user’s home directory."
|
|
|
|
|
.to_string(),
|
|
|
|
|
EX_UNAVAILABLE
|
|
|
|
|
));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
let mut root = false;
|
|
|
|
|
|
|
|
|
|
if unsafe { libc::geteuid() } == 0 { root = true; }
|
2023-03-25 19:58:41 +00:00
|
|
|
|
|
2023-03-25 20:23:26 +00:00
|
|
|
|
dir = match (root, env::var(xdg).ok()) {
|
|
|
|
|
(false, Some(var)) => var,
|
|
|
|
|
(su, None) => {
|
|
|
|
|
match xdg {
|
|
|
|
|
"XDG_CACHE_HOME" => {
|
|
|
|
|
if su { "/var".to_owned() }
|
|
|
|
|
else { format!("{}/.cache", home_dir) }
|
|
|
|
|
},
|
|
|
|
|
"XDG_CONFIG_HOME" => {
|
|
|
|
|
if su { "/etc".to_owned() }
|
|
|
|
|
else { format!("{}/.config", home_dir) }
|
|
|
|
|
},
|
|
|
|
|
"XDG_DATA_HOME" => {
|
|
|
|
|
if su { "/usr/share".to_owned() }
|
|
|
|
|
else { format!("{}/.local/share", home_dir) }
|
|
|
|
|
},
|
|
|
|
|
_ => {
|
|
|
|
|
return Err(
|
|
|
|
|
(format!("{}: Unimplemented variable.", xdg), EX_SOFTWARE)
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
_ => {
|
|
|
|
|
panic!("nya");
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
2023-03-25 19:58:41 +00:00
|
|
|
|
Ok(format!("{}/plaque", dir))
|
2023-03-08 07:00:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Config {
|
|
|
|
|
pub fn read_config(config_path: String) -> Result<Self, (String, u32)> {
|
|
|
|
|
let mut buf: Vec<u8> = Vec::new();
|
|
|
|
|
|
|
|
|
|
let mut config_file = match File::open(
|
|
|
|
|
format!("{}/config.toml", config_path)
|
|
|
|
|
) {
|
|
|
|
|
Ok(file) => file,
|
|
|
|
|
Err(err) => return Err((format!("{:?}", err), 1)),
|
|
|
|
|
};
|
|
|
|
|
|
2023-03-25 19:58:41 +00:00
|
|
|
|
if let Some(err) = config_file.read_to_end(&mut buf).err() {
|
|
|
|
|
return Err((format!("{:?}", err), EX_DATAERR));
|
|
|
|
|
}
|
2023-03-08 07:00:05 +00:00
|
|
|
|
|
|
|
|
|
let toml = String::from_utf8(buf).unwrap();
|
|
|
|
|
|
2023-03-25 19:58:41 +00:00
|
|
|
|
match toml::from_str(&toml) {
|
2023-03-08 07:00:05 +00:00
|
|
|
|
Ok(val) => Ok(val),
|
|
|
|
|
Err(err) => Err((format!("{:?}", err), 1)),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl PageMeta {
|
|
|
|
|
pub fn read_meta(toml: Value) -> Result<Self, (String, u32)> {
|
|
|
|
|
let input: String = match toml.try_into() {
|
|
|
|
|
Ok(val) => val,
|
|
|
|
|
Err(_) => {
|
|
|
|
|
return Err((format!("Failed to read page metadata."), EX_DATAERR));
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
match Self::deserialize(ValueDeserializer::new(&input)) {
|
|
|
|
|
Ok(val) => Ok(val),
|
|
|
|
|
Err(_) => {
|
2023-03-25 19:58:41 +00:00
|
|
|
|
Err(("Invalid configuration file.".to_owned(), EX_DATAERR))
|
2023-03-08 07:00:05 +00:00
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|