From 145f7cfd4035150d1f3d0d3d6923afe99114dc5a Mon Sep 17 00:00:00 2001
From: shim_ <>
Date: Sun, 4 Nov 2018 15:13:45 +0100
Subject: [PATCH] works(isch)
---
.dockerignore | 5 +
.gitignore | 11 ++
.idea/libraries/Cargo__brownpaper_.xml | 44 +++++++
.idea/vcs.xml | 6 +
Cargo.toml | 16 +++
Dockerfile | 9 ++
brownpaper.iml | 17 +++
src/main.rs | 158 +++++++++++++++++++++++++
8 files changed, 266 insertions(+)
create mode 100644 .dockerignore
create mode 100644 .gitignore
create mode 100644 .idea/libraries/Cargo__brownpaper_.xml
create mode 100644 .idea/vcs.xml
create mode 100644 Cargo.toml
create mode 100644 Dockerfile
create mode 100644 brownpaper.iml
create mode 100644 src/main.rs
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..b23303f
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,5 @@
+.*
+target/*/deps
+target/*/build
+target/*/.fingerprint
+target/*/incremental
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2a58023
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,11 @@
+# Generated by Cargo
+# will have compiled files and executables
+/target/
+
+# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
+# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock
+Cargo.lock
+
+#Intellj
+.iml
+.idea
diff --git a/.idea/libraries/Cargo__brownpaper_.xml b/.idea/libraries/Cargo__brownpaper_.xml
new file mode 100644
index 0000000..62dd3a4
--- /dev/null
+++ b/.idea/libraries/Cargo__brownpaper_.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..b56f667
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = "brownpaper"
+version = "0.1.0"
+authors = ["shim_ "]
+
+[dependencies]
+
+snap = "0.1"
+
+rustc-serialize = "0.3.19"
+
+iron = "0.6.0"
+
+rand = "0.4.2"
+
+chrono = { version = "0.2", features = ["rustc-serialize"] }
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..9d1951b
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,9 @@
+FROM scratch
+
+VOLUME /snips
+
+EXPOSE 3000
+
+COPY target/x86_64-unknown-linux-musl/release/brownpaper /bin/
+
+ENTRYPOINT [ "/bin/brownpaper" ]
\ No newline at end of file
diff --git a/brownpaper.iml b/brownpaper.iml
new file mode 100644
index 0000000..580f111
--- /dev/null
+++ b/brownpaper.iml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..c4a2664
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,158 @@
+extern crate chrono;
+extern crate iron;
+extern crate rand;
+extern crate snap;
+
+use chrono::*;
+use iron::method::Method;
+use iron::modifiers::Redirect;
+use iron::prelude::*;
+use iron::Url;
+use rand::Rng;
+use std::fs;
+use std::fs::File;
+use std::io;
+use std::io::prelude::*;
+use std::iter::Iterator;
+use std::path::{Path, PathBuf};
+
+struct Snippet<'a> {
+ id: String,
+ storage: &'a SnippetStorage<'a>,
+}
+
+struct SnippetMeta {
+ created: DateTime,
+ compression: Option,
+}
+
+struct SnippetStorage<'a> {
+ directory: &'a Path,
+}
+
+impl<'a> Snippet<'a> {
+ pub fn random(storage: &'a SnippetStorage) -> Snippet<'a> {
+ Snippet::new(
+ &rand::thread_rng()
+ .gen_ascii_chars()
+ .take(6)
+ .collect::(),
+ storage,
+ )
+ }
+
+ pub fn new(id: &str, storage: &'a SnippetStorage) -> Snippet<'a> {
+ Snippet {
+ id: id.to_string(),
+ storage,
+ }
+ }
+
+ pub fn path(&self) -> PathBuf {
+ self.storage.directory.join(&self.id)
+ }
+
+ fn metadata(&self) -> Result {
+ unimplemented!();
+ }
+
+ fn contents(&self) -> Result {
+ let mut file = File::open(self.path())?;
+ let mut text = String::new();
+ file.read_to_string(&mut text)?;
+ Ok(text)
+ }
+
+ fn write(self, content: &str) -> Result, io::Error> {
+ fs::write(self.path(), content).map(|_| self)
+ }
+}
+
+impl<'a> SnippetStorage<'a> {
+ pub fn new(directory: &'a Path) -> SnippetStorage<'a> {
+ SnippetStorage {
+ directory: directory,
+ }
+ }
+
+ fn has(&self, id: &str) -> bool {
+ self.directory.join(id).exists()
+ }
+
+ fn open(&self, id: &str) -> Option {
+ if self.has(id) {
+ Some(Snippet::new(id, self))
+ } else {
+ None
+ }
+ }
+}
+
+#[cfg(not(debug_assertions))]
+const STORAGE_DIR: &str = "/snips";
+
+#[cfg(debug_assertions)]
+const STORAGE_DIR: &str = "/tmp";
+
+fn handle(req: &mut Request) -> IronResult {
+ println!("{}", req.url);
+ let storage = SnippetStorage::new(&Path::new(STORAGE_DIR));
+ match req.method {
+ Method::Post => {
+ let segments: Vec<&str> = req.url.path();
+ if segments.first().iter().all(|seg| *seg == &"new") {
+ let snip = {
+ let text: String = {
+ let bytes = ((&mut req.body).bytes().take(1024 * 512).collect::,io::Error>>()).map_err(|err| IronError::new(err, ""))?;
+ String::from_utf8(bytes)
+ .map_err(|err| IronError::new(err, "Invalid utf8"))?
+ };
+ Snippet::random(&storage)
+ .write(&*text)
+ .map_err(|err| IronError::new(err, "Failed to save snippet"))
+ };
+ snip.map(|snip| {
+ let mut snip_url = req.url.clone().into_generic_url();
+ snip_url.set_path(&*("/".to_string() + &*snip.id));
+ /*Response::with((
+ iron::status::TemporaryRedirect,
+ Redirect(Url::from_generic_url(snip_url).unwrap()),
+ ))*/
+ Response::with((
+ iron::status::Ok,
+ format!("", snip_url)
+ ))
+ })
+ } else {
+ Ok(Response::with((iron::status::BadRequest, "Post to /new or die")))
+ }
+ }
+ Method::Get => {
+ let segments: Vec<&str> = req
+ .url
+ .path()
+ .into_iter()
+ .filter(|seg| seg.len() > 0)
+ .collect();
+ if segments.len() == 1 {
+ let id = &segments[0];
+ let att = storage.open(&id).map(|snip| snip.contents()).map(|res| {
+ Response::with(
+ res.map(|text| (iron::status::Ok, text))
+ .unwrap_or((iron::status::InternalServerError, "..".to_string())),
+ )
+ });
+ Ok(att.unwrap_or(Response::with((iron::status::NotFound, "Not here sry"))))
+ } else {
+ Ok(Response::with((iron::status::NotFound, "Wrong path pal")))
+ }
+ }
+ _ => Ok(Response::with((iron::status::BadRequest, "Give or take"))),
+ }
+}
+
+fn main() {
+ let chain = Chain::new(handle);
+ println!("Starting brownpaper: {}", STORAGE_DIR);
+ Iron::new(chain).http("0.0.0.0:3000").unwrap();
+}