aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCeleste <colean@colean.cc>2021-12-26 17:29:34 +0000
committerCeleste <colean@colean.cc>2021-12-26 17:29:34 +0000
commit736c1e6546bd489f747d477bcb9f20e0f7a59be2 (patch)
tree88711fc6a98505f52d1a5053b6a15e307e8e5f6a
parent8088fcdde6cc932e5034090a67df2bc649027ecb (diff)
Implement dynamic content via CGI and fix media type detection errors with server error pages.
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock4
-rw-r--r--Cargo.toml2
-rw-r--r--src/main.rs130
4 files changed, 101 insertions, 36 deletions
diff --git a/.gitignore b/.gitignore
index ea8c4bf..d0df1c9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
/target
+/src/content
diff --git a/Cargo.lock b/Cargo.lock
index 902a068..82b6ff9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,5 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+version = 3
+
[[package]]
name = "herb"
-version = "0.1.4"
+version = "0.3.0"
diff --git a/Cargo.toml b/Cargo.toml
index 1487a93..c3735d3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "herb"
-version = "0.2.0"
+version = "0.3.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
diff --git a/src/main.rs b/src/main.rs
index 1175818..ef75d9e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -5,40 +5,85 @@ use std::fs;
use std::string::{String};
use std::process::Command;
+fn process_cgi(filename: String) -> String {
+ // This is gonna be the boggiest implementation of CGI that anyone
+ // has ever seen in the history of the fucking world
+
+ let query;
+ let script;
+
+ if filename.contains("?") {
+ let vars = filename.to_string().find("?").unwrap();
+ let vars1 = vars + 1;
+ query = &filename[vars1..];
+ script = &filename[..vars];
+ println!("{} {}", query, script);
+ } else {
+ query = "";
+ script = &filename;
+ }
+
+
+ let output = Command::new(script)
+ .arg("GATEWAY_INTERFACE=\"CGI/1.1\"")
+ .arg("SERVER_SOFTWARE=\"Herb/0.3.0\"")
+ .arg("REQUEST_METHOD=\"GET\"")
+ .arg(format!("QUERY_STRING=\"{}\"", query))
+ .arg(format!("SCRIPT_NAME=\"{}\"", script))
+ .output()
+ .expect("failed to execute process");
+ let outputd = String::from_utf8_lossy(&output.stdout).to_string();
+ return outputd;
+}
+
fn detect_media_type(filename: String) -> String {
// The Lynx terminal browser made me do this.
- let ext_index = filename.to_string().find(".").unwrap();
- let test = ext_index + 1;
- let ext = &filename[test..];
-
- match ext {
- "aac" => "audio/aac".to_string(),
- "avi" => "video/x-msvideo".to_string(),
- "bmp" => "image/bmp".to_string(),
- "bz2" => "application/x-bzip2".to_string(),
- "css" => "text/css".to_string(),
- "gz" => "application/gzip".to_string(),
- "gif" => "image/gif".to_string(),
- "png" => "image/png".to_string(),
- "pdf" => "application/pdf".to_string(),
- "jpeg" => "image/jpeg".to_string(),
- "jpg" => "image/jpeg".to_string(),
- "js" => "text/javascript".to_string(),
- "mid" => "audio/midi".to_string(),
- "midi" => "audio/midi".to_string(),
- "mp3" => "audio/mpeg".to_string(),
- "mp4" => "video/mp4".to_string(),
- "mpeg" => "video/mpeg".to_string(),
- "ogg" => "audio/ogg".to_string(),
- "oga" => "audio/ogg".to_string(),
- "ogv" => "video/ogg".to_string(),
- "opus" => "audio/opus".to_string(),
- "txt" => "text/plain".to_string(),
- "html" => "text/html".to_string(),
- "htm" => "text/html".to_string(),
- _ => "application/octet-stream".to_string(),
+ let path = filename.to_string();
+ let paths = check_if_path_exists(path);
+ let path = filename.to_string();
+ let dir = check_if_dir(path);
+
+ if paths == true && dir == false && filename.contains(".") == false {
+ return "text/html".to_string();
+ } else {
+ let ext_index = filename.to_string().find(".").unwrap();
+ let test = ext_index + 1;
+ let ext = &filename[test..];
+
+ if filename[test..].contains("cgi") { return "text/html".to_string(); }
+
+ match ext {
+ "aac" => "audio/aac".to_string(),
+ "avi" => "video/x-msvideo".to_string(),
+ "bmp" => "image/bmp".to_string(),
+ "bz2" => "application/x-bzip2".to_string(),
+ "css" => "text/css".to_string(),
+ "gz" => "application/gzip".to_string(),
+ "gif" => "image/gif".to_string(),
+ "png" => "image/png".to_string(),
+ "pdf" => "application/pdf".to_string(),
+ "jpeg" => "image/jpeg".to_string(),
+ "jpg" => "image/jpeg".to_string(),
+ "js" => "text/javascript".to_string(),
+ "mid" => "audio/midi".to_string(),
+ "midi" => "audio/midi".to_string(),
+ "mp3" => "audio/mpeg".to_string(),
+ "mp4" => "video/mp4".to_string(),
+ "mpeg" => "video/mpeg".to_string(),
+ "ogg" => "audio/ogg".to_string(),
+ "oga" => "audio/ogg".to_string(),
+ "ogv" => "video/ogg".to_string(),
+ "opus" => "audio/opus".to_string(),
+ "txt" => "text/plain".to_string(),
+ "html" => "text/html".to_string(),
+ "htm" => "text/html".to_string(),
+ "cgi" => "text/html".to_string(),
+ ".error_server_404" => "text/html".to_string(),
+ ".error_server_503" => "text/html".to_string(),
+ _ => "application/octet-stream".to_string(),
+ }
}
}
@@ -91,8 +136,13 @@ fn get_page(filename: String) -> String {
println!("{} {} {}", path, checks, index);
if checks == true && index == false {
- if path.contains(".") != true {
+ if path.contains(".") != true && path.contains(".cgi?") != true {
let result = generate_index(filename);
+ println!("balls");
+ return result.to_string();
+ } else if path.contains(".cgi?") {
+ let result = process_cgi(filename);
+ println!("quack");
return result.to_string();
}
}
@@ -103,8 +153,13 @@ fn get_page(filename: String) -> String {
} else if filename == ".error_server_503" {
let result = "<!DOCTYPE HTML><html><body><h1>503 Not Implemented</h1><p>The request sent by your web browser cannot be handled by this server software.</p></body></html>";
return result.to_string();
+ } else if filename.contains(".cgi") {
+ let result = process_cgi(filename);
+ println!("cheese");
+ return result.to_string();
} else {
let result = fs::read_to_string(filename);
+ println!("e");
match result {
Ok(i) => i.to_string(),
Err(_e) => "<!DOCTYPE HTML><html><body><h1>403 Forbidden</h1><p>The resource you are trying to access cannot be read by the server.</p></body></html>".to_string(),
@@ -153,7 +208,9 @@ fn process_request(request: Vec<u8>) -> String {
chars.next();
let path = chars.as_str().to_string();
let exists = check_if_path_exists(path);
- if exists == false {
+ let path = chars.as_str().to_string();
+
+ if exists == false && path.contains(".cgi?") == false {
output = ".error_server_404";
} else {
let path = chars.as_str().to_string();
@@ -196,12 +253,17 @@ fn serve(mut stream: TcpStream) {
let resource = process_request(request);
// Haha, bodged my way around Rust's ownership paradigm!
- let mime = detect_media_type(resource.to_string());
+ let mime;
+ if resource.to_string().contains(".error") {
+ mime = "text/html".to_string();
+ } else {
+ mime = detect_media_type(resource.to_string());
+ }
let contents = get_page(resource);
let header = "HTTP/1.1 200 OK\r\n";
let content_type = format!("Content-Type: {}\r\n", mime);
- let server = "Server: Herb/0.2.0\r\n";
+ let server = "Server: Herb/0.3.0\r\n";
let extra_fields;
if cfg!(unix) {