~garritfra/public-inbox

taurus: Fallback to index.gmi, more modular code v3 NEEDS REVISION

Alexey Yerin: 1
 Fallback to index.gmi, more modular code

 2 files changed, 47 insertions(+), 27 deletions(-)
And, don't forget to sign off the commits ;)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~garritfra/public-inbox/patches/14837/mbox | git am -3
Learn more about email & git
View this thread in the archives

[PATCH taurus v3] Fallback to index.gmi, more modular code Export this patch

---
Fix vulnerability

 src/gemini.rs | 10 +++++++-
 src/main.rs   | 64 ++++++++++++++++++++++++++++++---------------------
 2 files changed, 47 insertions(+), 27 deletions(-)

diff --git a/src/gemini.rs b/src/gemini.rs
index 1dd3c85..5f9cb3b 100644
--- a/src/gemini.rs
+++ b/src/gemini.rs
@@ -14,13 +14,21 @@ impl GeminiRequest {
        Ok(gemini_request)
    }

    pub fn file_path(&self) -> Option<&str> {
    fn unsafe_file_path(&self) -> Option<&str> {
        self.path
            .path()
            .chars()
            .next()
            .map(|c| &self.path.path()[c.len_utf8()..])
    }

    pub fn file_path(&self) -> Option<&str> {
        match self.unsafe_file_path() {
            Some(path) if path.contains("..") || path.starts_with("/") => None,
            Some(path) => Some(path),
            None => None,
        }
    }
}

fn parse_path(req: &str) -> Option<&str> {
diff --git a/src/main.rs b/src/main.rs
index d3557b1..47a4ea3 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -5,6 +5,7 @@ mod gemini;

use native_tls::{Identity, TlsAcceptor, TlsStream};
use std::fs::File;
use std::io;
use std::io::Read;
use std::io::Write;
use std::net::TcpListener;
@@ -39,11 +40,43 @@ fn main() {
                    Err(e) => println!("Can't handle stream: {}", e),
                });
            }
            Err(_e) => println!("Error: {}", _e),
            Err(err) => println!("Error: {}", err),
        }
    }
}

/// Helper function to read a file into Vec
fn read_file(file_path: &str) -> Result<Vec<u8>, io::Error> {
    let mut file = File::open(file_path)?;
    let mut buf = Vec::new();

    file.read_to_end(&mut buf)?;

    Ok(buf)
}

/// Send file as a response
fn send_file(path: &str, response: &mut gemini::GeminiResonse) {
    match read_file(path) {
        Ok(buf) => {
            response.body = Some(buf);
        }
        Err(err) => {
            // Cannot read file or it doesn't exist

            println!("Error ({}): {}", path, err);

            response.status = [b'5', b'1'];
            response.meta = format!("Resource not found: {}", path).into();
        }
    }
}

fn redirect(path: &str, response: &mut gemini::GeminiResonse) {
    response.status = [b'3', b'1'];
    response.meta = path.into();
}

fn handle_client(mut stream: TlsStream<TcpStream>) {
    let mut buffer = [0; 1024];
    if let Err(e) = stream.read(&mut buffer) {
@@ -60,31 +93,10 @@ fn handle_client(mut stream: TlsStream<TcpStream>) {
    let request = gemini::GeminiRequest::from_string(&raw_request).unwrap();
    let mut response = gemini::GeminiResonse::new();

    match request.file_path() {
        Some(file_path) => {
            println!("Reading {}", file_path);

            match File::open(file_path) {
                Ok(mut file) => {
                    let mut body_buf = Vec::new();
                    if let Err(e) = file.read_to_end(&mut body_buf) {
                        println!("Could not read file {}", e);
                    }

                    response.body = Some(body_buf);
                }
                Err(e) => {
                    let file_path = request.file_path().unwrap_or("");
                    println!("Error ({}): {}", file_path, e);
                    response.status = [b'5', b'1'];
                    response.meta = format!("Resource not found: {}", file_path).into();
                }
            }
        }
        None => {
            println!("No file found in request");
            response.status = [b'5', b'1']
        }
    if let Some(path) = request.file_path() {
        send_file(path, &mut response);
    } else {
        redirect("/index.gmi", &mut response);
    }

    if let Err(e) = stream.write(&response.build()) {
-- 
2.29.2
Can you send the commits again as a patch-series? I can't apply this
on it's own, and for some reason also not on top of your previous
patch.