aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVojtěch Pejša <vojtechpejsa7@gmail.com>2019-03-27 08:44:29 +0000
committerVojtěch Pejša <vojtechpejsa7@gmail.com>2019-04-04 08:51:00 +0000
commitd14e17d94964291fda976423c1fe1a772d5af60b (patch)
tree0515e663527bd59fc74e2649e185ee1fbcda785a /src
parentUse proper typed query param. (diff)
downloadminiserve-d14e17d94964291fda976423c1fe1a772d5af60b.tar.gz
miniserve-d14e17d94964291fda976423c1fe1a772d5af60b.zip
Add CLI arguments for file uploading.
Diffstat (limited to '')
-rw-r--r--src/args.rs10
-rw-r--r--src/file_upload.rs13
-rw-r--r--src/listing.rs2
-rw-r--r--src/main.rs25
-rw-r--r--src/renderer.rs3
5 files changed, 44 insertions, 9 deletions
diff --git a/src/args.rs b/src/args.rs
index 4f0dbf7..7fa5121 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -47,6 +47,14 @@ struct CLIArgs {
/// Do not follow symbolic links
#[structopt(short = "P", long = "no-symlinks")]
no_symlinks: bool,
+
+ /// Enable file uploading
+ #[structopt(short = "u", long = "upload-files")]
+ file_upload: bool,
+
+ /// Enable overriding existing files during file upload
+ #[structopt(short = "o", long = "owerride-files")]
+ override_files: bool,
}
/// Checks wether an interface is valid, i.e. it can be parsed into an IP address
@@ -100,5 +108,7 @@ pub fn parse_args() -> crate::MiniserveConfig {
path_explicitly_chosen,
no_symlinks: args.no_symlinks,
random_route,
+ override_files: args.override_files,
+ file_upload: args.file_upload,
}
}
diff --git a/src/file_upload.rs b/src/file_upload.rs
index dd4c962..9f87724 100644
--- a/src/file_upload.rs
+++ b/src/file_upload.rs
@@ -20,7 +20,11 @@ struct QueryParameters {
fn save_file(
field: multipart::Field<dev::Payload>,
file_path: PathBuf,
+ override_files: bool,
) -> Box<Future<Item = i64, Error = Error>> {
+ if !override_files && file_path.exists() {
+ return Box::new(future::err(error::ErrorInternalServerError("file exists")));
+ }
let mut file = match std::fs::File::create(file_path) {
Ok(file) => file,
Err(e) => return Box::new(future::err(error::ErrorInternalServerError(e))),
@@ -42,6 +46,7 @@ fn save_file(
fn handle_multipart(
item: multipart::MultipartItem<dev::Payload>,
mut file_path: PathBuf,
+ override_files: bool,
) -> Box<Stream<Item = i64, Error = Error>> {
match item {
multipart::MultipartItem::Field(field) => {
@@ -60,15 +65,14 @@ fn handle_multipart(
match filename {
Ok(f) => {
file_path = file_path.join(f);
- // TODO should I allow overriding existing files?
- Box::new(save_file(field, file_path).into_stream())
+ Box::new(save_file(field, file_path, override_files).into_stream())
}
Err(e) => Box::new(e.into_stream()),
}
}
multipart::MultipartItem::Nested(mp) => Box::new(
mp.map_err(error::ErrorInternalServerError)
- .map(move |item| handle_multipart(item, file_path.clone()))
+ .map(move |item| handle_multipart(item, file_path.clone(), override_files))
.flatten(),
),
}
@@ -101,10 +105,11 @@ pub fn upload_file(req: &HttpRequest<crate::MiniserveConfig>) -> FutureResponse<
Ok(path) if path.starts_with(&app_root_dir) => path.clone(),
_ => return Box::new(future::ok(HttpResponse::BadRequest().body("Invalid path"))),
};
+ let override_files = req.state().override_files;
Box::new(
req.multipart()
.map_err(error::ErrorInternalServerError)
- .map(move |item| handle_multipart(item, target_dir.clone()))
+ .map(move |item| handle_multipart(item, target_dir.clone(), override_files))
.flatten()
.collect()
.map(move |_| {
diff --git a/src/listing.rs b/src/listing.rs
index 0173176..5fde879 100644
--- a/src/listing.rs
+++ b/src/listing.rs
@@ -130,6 +130,7 @@ pub fn directory_listing<S>(
dir: &fs::Directory,
req: &HttpRequest<S>,
skip_symlinks: bool,
+ file_upload: bool,
random_route: Option<String>,
) -> Result<HttpResponse, io::Error> {
let title = format!("Index of {}", req.path());
@@ -265,6 +266,7 @@ pub fn directory_listing<S>(
page_parent,
sort_method,
sort_order,
+ file_upload,
&base.to_string_lossy(),
)
.into_string(),
diff --git a/src/main.rs b/src/main.rs
index fb7e321..f7d0b1b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -44,6 +44,12 @@ pub struct MiniserveConfig {
/// Enable random route generation
pub random_route: Option<String>,
+
+ /// Enable file upload
+ pub file_upload: bool,
+
+ /// Enable upload to override existing files
+ pub override_files: bool,
}
fn main() {
@@ -175,11 +181,12 @@ fn main() {
}
/// Configures the Actix application
-fn configure_app(app: App<MiniserveConfig>) -> App<MiniserveConfig> {
+fn configure_app(mut app: App<MiniserveConfig>) -> App<MiniserveConfig> {
let s = {
let path = &app.state().path;
let no_symlinks = app.state().no_symlinks;
let random_route = app.state().random_route.clone();
+ let file_upload = app.state().file_upload.clone();
if path.is_file() {
None
} else {
@@ -188,7 +195,13 @@ fn configure_app(app: App<MiniserveConfig>) -> App<MiniserveConfig> {
.expect("Couldn't create path")
.show_files_listing()
.files_listing_renderer(move |dir, req| {
- listing::directory_listing(dir, req, no_symlinks, random_route.clone())
+ listing::directory_listing(
+ dir,
+ req,
+ no_symlinks,
+ file_upload,
+ random_route.clone(),
+ )
}),
)
}
@@ -198,9 +211,11 @@ fn configure_app(app: App<MiniserveConfig>) -> App<MiniserveConfig> {
let full_route = format!("/{}", random_route);
// Allow file upload
- let app = app.resource("/upload", |r| {
- r.method(Method::POST).f(file_upload::upload_file)
- });
+ if app.state().file_upload {
+ app = app.resource("/upload", |r| {
+ r.method(Method::POST).f(file_upload::upload_file)
+ });
+ }
if let Some(s) = s {
// Handle directories
diff --git a/src/renderer.rs b/src/renderer.rs
index 3039dc7..6b3fb9f 100644
--- a/src/renderer.rs
+++ b/src/renderer.rs
@@ -14,6 +14,7 @@ pub fn page(
page_parent: Option<String>,
sort_method: Option<listing::SortingMethod>,
sort_order: Option<listing::SortingOrder>,
+ file_upload: bool,
base: &str,
) -> Markup {
html! {
@@ -21,11 +22,13 @@ pub fn page(
body {
span #top { }
h1 { (page_title) }
+ @if file_upload {
form action={"/upload?path=" (base)} method="POST" enctype="multipart/form-data" {
p { "Select file to upload" }
input type="file" name="file_to_upload" {}
input type="submit" value="Upload file" {}
}
+ }
div.download {
(archive_button(archive::CompressionMethod::TarGz))
}