DK6254GRWC6DVMLYWI5WSKDFX2EE4R24ZT3IQWIWJJUIOKKVKWMQC // sparqlpuppy - an LDP/SOLID Server// Copyright (C) 2019 Azure <azure@fox.blue>//// This program 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.//// This program 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/>.mod rdf {pub static TYPE: &str = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type";}mod ldp {pub static CONTAINER: &str = "http://www.w3.org/ns/ldp#Container";pub static RESOURCE: &str = "http://www.w3.org/ns/ldp#Resource";pub static BASIC_CONTAINER: &str = "http://www.w3.org/ns/ldp#BasicContainer";pub static CONTAINS: &str = "http://www.w3.org/ns/ldp#contains";}mod stat {pub static FILE: &str = "http://www.w3.org/ns/posix/stat#File";pub static DIR: &str = "http://www.w3.org/ns/posix/stat#Directory";pub static MTIME: &str = "http://www.w3.org/ns/posix/stat#mtime";pub static SIZE: &str = "http://www.w3.org/ns/posix/stat#size";}
// sparqlpuppy - an LDP/SOLID Server// Copyright (C) 2020 Azure <azure@fox.blue>//// This program 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.//// This program 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 crate::SETTINGS;use fehler::throws;use http_types::{ensure, Error};#[throws]pub async fn create_container() {}
// sparqlpuppy - an LDP/SOLID Server// Copyright (C) 2020 Azure <azure@fox.blue>//// This program 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.//// This program 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 crate::files;use crate::{SETTINGS, STORE};use async_std::{fs, io::ErrorKind, net::SocketAddr, path::Path, path::PathBuf};use fehler::{throw, throws};use http_types::{ensure, Error};use itertools::iproduct;use oxigraph::store::rocksdb::RocksDbStore;#[derive(Debug)]pub struct Config {/// Path where uploaded files are storedpub file_path: PathBuf,/// Path to the RDF tuplestorepub db_path: PathBuf,/// Address to bind the socket topub addr: SocketAddr,}#[throws]fn configure() {let mut settings = config::Config::default();settings.set_default("file_path", "/srv/sparqlpuppy/files/")?;settings.set_default("db_path", "/srv/sparqlpuppy/db/")?;settings.set_default("addr", "127.0.0.1:8080")?;settings.merge(config::Environment::with_prefix("SPARQLPUPPY"))?;SETTINGS.set(Config {file_path: settings.get_str("file_path")?.into(),db_path: settings.get_str("db_path")?.into(),addr: settings.get_str("addr")?.parse()?,}).unwrap()}#[throws]async fn mkhier(path: impl AsRef<Path>) {let m = fs::metadata(&path).await;match m {Err(e) => {if e.kind() == ErrorKind::NotFound {fs::create_dir_all(&path).await?} else {throw!(e)}}Ok(m) => ensure!(m.is_dir(),"{:?} exists but is not a directory",path.as_ref()),}}#[throws]async fn create_filehier() {let settings = SETTINGS.get().unwrap();let hexits = [Path::new("0"),Path::new("1"),Path::new("2"),Path::new("3"),Path::new("4"),Path::new("5"),Path::new("6"),Path::new("7"),Path::new("8"),Path::new("9"),Path::new("a"),Path::new("b"),Path::new("c"),Path::new("d"),Path::new("e"),Path::new("f"),];let base = settings.file_path.as_path();for (i, j, k) in iproduct!(&hexits, &hexits, &hexits) {let path: PathBuf = [base, i, j, k].iter().collect();mkhier(path).await?}let path: PathBuf = [base, Path::new("ephem")].iter().collect();fs::remove_dir_all(&path).await?;mkhier(path).await?;}#[throws]pub async fn setup() {configure()?;create_filehier().await?;let settings = SETTINGS.get().unwrap();ensure!(STORE.set(RocksDbStore::open(&settings.db_path)?).is_ok(),"Can't happen: Unable to store database handle.");}
// sparqlpuppy - an LDP/SOLID Server// Copyright (C) 2019 Azure <azure@fox.blue>//// This program 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.//// This program 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 http_types::Result;use rio_api::formatter::TriplesFormatter;use rio_api::model::{Literal, NamedNode, Triple};use rio_turtle::TurtleFormatter;use std::fs::Metadata;use std::io::Write;use std::time::SystemTime;use crate::urls::{BASIC_CONTAINER, CONTAINER, CONTAINS, STAT_DIR, STAT_FILE, STAT_MTIME, STAT_SIZE, TYPE,};pub fn is_container<W: Write>(formatter: &mut TurtleFormatter<W>, iri: &str) -> Result<()> {formatter.format(&Triple {subject: NamedNode { iri }.into(),predicate: NamedNode { iri: TYPE },object: NamedNode { iri: CONTAINER }.into(),})?;Ok(())}pub fn is_basic_container<W: Write>(formatter: &mut TurtleFormatter<W>, iri: &str) -> Result<()> {formatter.format(&Triple {subject: NamedNode { iri }.into(),predicate: NamedNode { iri: TYPE },object: NamedNode {iri: BASIC_CONTAINER,}.into(),})?;Ok(())}pub fn contains<W: Write>(formatter: &mut TurtleFormatter<W>, c: &str, d: &str) -> Result<()> {formatter.format(&Triple {subject: NamedNode { iri: c }.into(),predicate: NamedNode { iri: CONTAINS },object: NamedNode { iri: d }.into(),})?;Ok(())}pub fn posix<W: Write>(formatter: &mut TurtleFormatter<W>, iri: &str, m: &Metadata) -> Result<()> {if m.is_file() {formatter.format(&Triple {subject: NamedNode { iri }.into(),predicate: NamedNode { iri: TYPE },object: NamedNode { iri: STAT_FILE }.into(),})?;} else if m.is_dir() {formatter.format(&Triple {subject: NamedNode { iri }.into(),predicate: NamedNode { iri: TYPE },object: NamedNode { iri: STAT_DIR }.into(),})?;}if let Ok(mt) = m.modified() {if let Ok(mtime) = mt.duration_since(SystemTime::UNIX_EPOCH) {let secs = mtime.as_secs().to_string();formatter.format(&Triple {subject: NamedNode { iri }.into(),predicate: NamedNode { iri: STAT_MTIME },object: Literal::Simple { value: &secs }.into(),})?;}}let len = m.len().to_string();formatter.format(&Triple {subject: NamedNode { iri }.into(),predicate: NamedNode { iri: STAT_SIZE },object: Literal::Simple { value: &len }.into(),})?;Ok(())}
// sparqlpuppy - an LDP/SOLID Server// Copyright (C) 2020 Azure <azure@fox.blue>//// This program 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.//// This program 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/>.#![forbid(unsafe_code)]mod files;mod setup;mod store;mod urls;use crate::setup::Config;use async_std::{net::{TcpListener, TcpStream},prelude::*,task,};use fehler::throws;use http_types::{Error, Request, Response, StatusCode};use once_cell::sync::OnceCell;use oxigraph::store::rocksdb::RocksDbStore;static SETTINGS: OnceCell<Config> = OnceCell::new();static STORE: OnceCell<RocksDbStore> = OnceCell::new();#[throws]#[async_std::main]async fn main() {setup::setup().await?;let settings = SETTINGS.get().unwrap();let listener = TcpListener::bind(&settings.addr).await?;// For each incoming TCP connection, spawn a task and call `accept`.let mut incoming = listener.incoming();while let Some(stream) = incoming.next().await {let stream = stream?;task::spawn(async {if let Err(err) = accept(stream).await {eprintln!("{}", err);}});}}#[throws]async fn accept(stream: TcpStream) {async_h1::accept(stream.clone(), |req| async { req_handler(req).await }).await?;}pub static BASIC_CONTAINER: &str = "<http://www.w3.org/ns/ldp#BasicContainer>; rel=\"type\"";// static RESOURCE: &str =// "<http://www.w3.org/ns/ldp#Resource>; rel=\"type\"";// static TURTLE_TYPE: &str = "text/turtle; charset=UTF-8";// static ALLOWABLES: &str = "OPTIONS,HEAD,GET,POST,PUT,PATCH";// static PATCHABLES: &str = "text/ldpatch";// static POSTABLES: &str = "text/turtle, application/ld+json, image/bmp, image/jpeg";#[throws]async fn req_handler(_req: Request) -> Response {// let reqpath = req.url().path().trim_start_matches('/');return Response::new(StatusCode::Ok);}
// sparqlpuppy - an LDP/SOLID Server// Copyright (C) 2020 Azure <azure@fox.blue>//// This program 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.//// This program 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 crate::SETTINGS;use fehler::throws;use http_types::{ensure, Error};
# sparqlpuppysparqlpuppy is written in Rust and wants to be a Linked DataPlatform/SoLiD server when it grows up.## InstallationFetch from https://git.sr.ht/~azure/sparqlpuppy and build with cargo.## Usagesparqlpuppy is configured with environmentvariables. `SPARQLPUPPY_LISTEN`, defaulting to `127.0.0.1:8080`, and`SPARQLPUPPY_ROOT`, defaulting to, `/srv/ldp`.## ContributingPatchsets are welcome. For major changes, please open an issue firstto discuss what you would like to change.Please make sure to update tests as appropriate.## License[AGPL3](https://www.gnu.org/licenses/agpl-3.0.en.html)
[package]name = "sparqlpuppy"version = "0.1.0"authors = ["Azure <azure@fox.blue>"]edition = "2018"publish = falsedescription = "An experimental SOLID Server"license = "AGPL-3.0-or-later"repository = "https://git.sr.ht/~azure/sparqlpuppy"readme = "README.md"[dependencies]async-h1 = "^2.1"async-native-tls = "~0.3"async-std = { version = "^1.6", features = ["attributes", "unstable"] }config = "~0.10"fehler = "^1"futures = "~0.3"http-types = "^2.4.0"itertools = "~0.9"mime = "~0.3"once_cell = "^1.4"oxigraph = { version = "~0.1", features = ["rocksdb"] }rio_api = "~0.5"rio_turtle = "~0.5"[profile.release]lto = "fat"codegen-units = 1
# The Rust Code of Conduct #The Code of Conduct for this repository [can be foundonline](https://www.rust-lang.org/conduct.html).