use std::fs; use std::path::Path; use std::io::prelude::*; use std::net::TcpListener; use std::net::TcpStream; extern crate argparse; use argparse::{ArgumentParser, StoreTrue, Store}; fn main() { let mut verbose = false; let mut host = "localhost".to_string(); let mut port = 3000; // TODO: change to 300 //let mut root_dir = format!("/home/{}/public_spartan/", "username"); // Arguments { let mut ap = ArgumentParser::new(); ap.set_description("Experimental spartan server"); ap.refer(&mut verbose) .add_option(&["-v", "--verbose"], StoreTrue, "Be verbose"); ap.refer(&mut host) .add_option(&["--host"], Store, "Hostname"); ap.refer(&mut port) .add_option(&["-p", "--port"], Store, "Port"); /*ap.refer(&mut root_dir) .add_option(&["-d", "--root-dir"], Store, "Root directory");*/ ap.parse_args_or_exit(); } if verbose { println!("Work in progress"); } let listener = TcpListener::bind(format!("{}:{}", host, port)).unwrap(); for stream in listener.incoming() { let stream = stream.unwrap(); handle_connection(stream); } } fn handle_connection(mut stream: TcpStream) { let mut buffer = [0; 1024]; stream.read(&mut buffer).unwrap(); println!("{}", String::from_utf8_lossy(&buffer[..])); // let _echo = b"$hostname /echo 0\r\n"; // TODO: fix echo behaviour let request = String::from_utf8_lossy(&buffer[..]); let parsed_request: Vec<&str> = request.split(' ').collect(); let host = parsed_request[0]; let _path = parsed_request[1]; let _post_len = parsed_request[2]; let mut _post = ""; // TODO: fix behaviour for post /* if _post_len.len() > 0 { let _post = parsed_request[3]; } else { let _post = ""; }*/ let get = format!( "{} {} {}\r\n {}\r\n", host, _path, _post_len, _post); let _get_bytes = get.as_bytes(); let status_line = if Path::new(&format!("{}{}", "/home/g1n/public_spartan", _path).to_string()).exists() { "2 text/gemini" } else { "4 Not found" }; //let filename = "index.gmi"; /* let _contents = ""; if _filename != "" { let _contents = fs::read_to_string(_filename).unwrap(); } else { */ let mut _contents = "".to_string(); let full_path = format!("{}{}", "/home/g1n/public_spartan", _path); let mut exists = Path::new(&format!("{}{}", "/home/g1n/public_spartan", _path).to_string()).exists(); if exists { if Path::new(&full_path).is_file(){ _contents = fs::read_to_string(format!("{}{}", "/home/g1n/public_spartan", _path)).unwrap(); } else { exists = Path::new(&format!("{}{}/index.gmi", "/home/g1n/public_spartan", _path).to_string()).exists(); if exists { _contents = fs::read_to_string(format!("{}{}index.gmi", "/home/g1n/public_spartan", _path)).unwrap(); } else { _contents = format!("=> ..\n"); let path_to_folder = full_path.clone(); let files = fs::read_dir(path_to_folder).unwrap(); for file in files { let path_to_folder = full_path.clone(); let path = file.unwrap().path(); let file = path.strip_prefix(path_to_folder); let file = file.unwrap().display(); if path.is_dir() { _contents += &format!("=> {}/\n", file).to_string(); } else { _contents += &format!("=> {}\n", file).to_string(); } } } } } let response = format!( "{}\r\n {}", status_line, _contents ); stream.write(response.as_bytes()).unwrap(); stream.flush().unwrap(); }